<commit_before>const SimpleClient = require("./client.js");

class Command {
    /**
     * @typedef {Object} CommandOptions
     * @property {string} name - The command name.
     * @property {string} description - The command description.
     * @property {Array<Array<string, boolean>>} use - The command arguments.
     * @property {Array<string>} aliases - Aliases for the command.
     * @property {Array<string>} permissions - Permissions required to run the command.
     * @property {boolean} guildOnly - If the command can only be run in a guild.
     * @property {boolean} ownerOnly - If the command can only be run by a bot owner.
     * @property {ThrottlingOptions} throttling - Options for throttling usages for the command.
     */

     /**
  	  * @typedef {Object} ThrottlingOptions
 	  * @property {number} usages - Maximum number of usages of the command allowed in the specified duration.
 	  * @property {number} duration - Amount of time to count the usages of the command within (in seconds).
 	  */

    /**
     * @class
     * @classdesc A SimpleDiscord command.
     * @param {SimpleClient} client - The client object.
     * @param {CommandOptions} options - Options for the commands.
     */
    constructor(client, options) {
        this.client = client;
        this.name = options.name;
        this.type = options.type;
        this.description = options.description;
        this.use = options.use;
        this.aliases = options.aliases;
        this.permissions = options.permissions;
        this.guildOnly = !!options.guildOnly;
        this.ownerOnly = !!options.ownerOnly;
        this.throttling = options.throttling;

        this._validateCommand();

        /**
         * Holds throttlings.
         * @type {Map<string, Snowflake>}
         * @private
         */
        this._throttling = new Map();
    }

    /**
	 * Keeps track if the user needs to be throttled, if necessary.
	 * @param {string} user - ID of the user
	 * @returns {boolean}
	 */
    throttle(user) {
        if (this.client._owners.includes(user)) return;

        const throttling = (this._throttling.has(user) ? this._throttling.get(user) : {dateline:Date.now(), lastusage:0, usages:0});

        if (throttling.dateline + (this.throttling.duration * 1000) < Date.now()) {
            throttling.dateline = Date.now();
            throttling.lastusage = 0;
            throttling.usages = 0;
        }

        if ((throttling.lastusage > 0 && (throttling.lastusage - throttling.dateline) / 1000) <= this.throttling.duration && throttling.usages >= this.throttling.usages) return true;

        throttling.lastusage = Date.now();
        throttling.usages++;

        this._throttling.set(user, throttling);

        return false;
    }

    /**
     * Verifies the command configuration is valid.
     * @function _validateCommand
     * @private
     */
    _validateCommand() {
        if (!(this.client instanceof SimpleClient)) throw new TypeError("Simple-Discord - Command constructor parameter client must be the SimpleDiscord client.");

        if (!this.name) throw new Error("Simple-Discord - Command name is required.");
        if (!this.type) throw new Error("Simple-Discord - Command type is required.");
        if (!this.description) throw new Error("Simple-Discord - Command description is required.");
        if (this.throttling && (typeof this.throttling.usages !== 'number' || typeof this.throttling.duration !== 'number')) throw new Error('Simple-Discord - Command throttling contains invalid parameters.');
    }

    /**
     * The command to be run.
     * @function run
     * @abstract
     * @param {Message} message - The discord.js message object.
     * @param {Array<any>} args - The command arguments.
     */
    run(message, args) { // eslint-disable-line no-unused-vars
        throw new TypeError(`Simple-Discord - The command file ${this.name} does not have a run function.`);
    }
}

module.exports = Command;
<commit_msg>Remove unnecessary eslint-disable-line comment<commit_after>const SimpleClient = require("./client.js");

class Command {
    /**
     * @typedef {Object} CommandOptions
     * @property {string} name - The command name.
     * @property {string} description - The command description.
     * @property {Array<Array<string, boolean>>} use - The command arguments.
     * @property {Array<string>} aliases - Aliases for the command.
     * @property {Array<string>} permissions - Permissions required to run the command.
     * @property {boolean} guildOnly - If the command can only be run in a guild.
     * @property {boolean} ownerOnly - If the command can only be run by a bot owner.
     * @property {ThrottlingOptions} throttling - Options for throttling usages for the command.
     */

     /**
  	  * @typedef {Object} ThrottlingOptions
 	  * @property {number} usages - Maximum number of usages of the command allowed in the specified duration.
 	  * @property {number} duration - Amount of time to count the usages of the command within (in seconds).
 	  */

    /**
     * @class
     * @classdesc A SimpleDiscord command.
     * @param {SimpleClient} client - The client object.
     * @param {CommandOptions} options - Options for the commands.
     */
    constructor(client, options) {
        this.client = client;
        this.name = options.name;
        this.type = options.type;
        this.description = options.description;
        this.use = options.use;
        this.aliases = options.aliases;
        this.permissions = options.permissions;
        this.guildOnly = !!options.guildOnly;
        this.ownerOnly = !!options.ownerOnly;
        this.throttling = options.throttling;

        this._validateCommand();

        /**
         * Holds throttlings.
         * @type {Map<string, Snowflake>}
         * @private
         */
        this._throttling = new Map();
    }

    /**
	 * Keeps track if the user needs to be throttled, if necessary.
	 * @param {string} user - ID of the user
	 * @returns {boolean}
	 */
    throttle(user) {
        if (this.client._owners.includes(user)) return;

        const throttling = (this._throttling.has(user) ? this._throttling.get(user) : {dateline:Date.now(), lastusage:0, usages:0});

        if (throttling.dateline + (this.throttling.duration * 1000) < Date.now()) {
            throttling.dateline = Date.now();
            throttling.lastusage = 0;
            throttling.usages = 0;
        }

        if ((throttling.lastusage > 0 && (throttling.lastusage - throttling.dateline) / 1000) <= this.throttling.duration && throttling.usages >= this.throttling.usages) return true;

        throttling.lastusage = Date.now();
        throttling.usages++;

        this._throttling.set(user, throttling);

        return false;
    }

    /**
     * Verifies the command configuration is valid.
     * @function _validateCommand
     * @private
     */
    _validateCommand() {
        if (!(this.client instanceof SimpleClient)) throw new TypeError("Simple-Discord - Command constructor parameter client must be the SimpleDiscord client.");

        if (!this.name) throw new Error("Simple-Discord - Command name is required.");
        if (!this.type) throw new Error("Simple-Discord - Command type is required.");
        if (!this.description) throw new Error("Simple-Discord - Command description is required.");
        if (this.throttling && (typeof this.throttling.usages !== 'number' || typeof this.throttling.duration !== 'number')) throw new Error('Simple-Discord - Command throttling contains invalid parameters.');
    }

    /**
     * The command to be run.
     * @function run
     * @abstract
     * @param {Message} message - The discord.js message object.
     * @param {Array<any>} args - The command arguments.
     */
    run(message, args) {
        throw new TypeError(`Simple-Discord - The command file ${this.name} does not have a run function.`);
    }
}

module.exports = Command;
<|endoftext|>


<commit_before>'use strict';

;(function(app) {
  app
  .config(['tokenProvider', function(tokenProvider) {
    tokenProvider.setUrl('token')
  }])
  .controller('uploads.controllers', [
    '$scope',
    '$http',
    '$log',
    '$sessionStorage',
    'token',
    'uploadsUtils',
    'FileUploader',
    function($scope, $http, $log, $sessionStorage, _token, utils, FileUploader) {
      $scope.$storage = $sessionStorage;
      $scope.tokenStatus = 'missing';

      // token should be a JSON object containing the Policy and Signature
      // which are part of the tokens for AWS Uploads
      var token,
          isFileTooBig;

      var uploader = $scope.uploader = new FileUploader();

      _token.success(function(data) {
        $scope.tokenStatus = 'received'
        // Define policy and signature for AWS upload
        token = data;

        // Url to hit for the post request
        uploader.url = token.url;
      })
      .error(function() {
        throw new Error('Couldn\'t retreive AWS credentials');
      })

      // Add the img in session storage once added
      uploader.onAfterAddingFile = function(fileItem) {
        // Updates the formData for Amazon AWS S3 Upload
        fileItem.formData.push({
          key:  fileItem.file.name,
          AWSAccessKeyId: token.AWSKey,
          acl: 'private',
          'Content-Type': (fileItem.file.type !== '') ? fileItem.file.type : 'application/octet-stream',
          filename: fileItem.file.name,
          policy: token.policy,
          signature: token.signature
        });

        if (isFileTooBig)
          return;

        var reader = new FileReader();

        // Turns img into a dataUrl so it can
        // be stored in the session storage
        reader.readAsDataURL(fileItem._file);
        reader.onload = onLoad;

        try {
          $scope.$storage.reader = reader;
        } catch(e) {
          throw new Error(e);
          isFileTooBig = true;
        }

        // To resize the picture we need a hidden canvas
        // to draw a new pic with the expected dimensions
        var canvas = document.createElement('canvas');
        canvas.style.visibility = 'hidden';
        document.body.appendChild(canvas);

        // Wait for the reader to be loaded to get the right img.src
        function onLoad(event) {
          var img = new Image();
          img.onload = utils.getDimensions(canvas, $scope.$storage);
          img.src = event.target.result;
        }
      };

      uploader.onBeforeUploadItem = function(fileItem) {
        // Parse the item stored in session storage
        // before the server upload
        if (!isFileTooBig)
          fileItem._file = utils.dataURItoBlob($scope.$storage.reader);
      };

      uploader.onCompleteItem = function(fileItem, response, status, headers) {
        // Empty the session storage once the item has been uploaded
        delete $scope.$storage.reader;
      };

      uploader.onErrorItem = function(fileItem, response, status, headers) {
        // TODO: try to reupload the img
      };
    }]);

})(angular.module('uploads.controllers', ['token', 'angularFileUpload', 'ngStorage']))
<commit_msg>formatting<commit_after>'use strict';

;(function(app) {

  app.config(['tokenProvider', function(tokenProvider) {
    tokenProvider.setUrl('token')
  }]);

  app.controller('uploads.controllers',
    ['$scope', '$http', '$log', '$sessionStorage', 'token', 'uploadsUtils', 'FileUploader',
    function($scope, $http, $log, $sessionStorage, _token, utils, FileUploader) {
      $scope.$storage = $sessionStorage;
      $scope.tokenStatus = 'missing';

      // token should be a JSON object containing the Policy and Signature
      // which are part of the tokens for AWS Uploads
      var token,
          isFileTooBig;

      var uploader = $scope.uploader = new FileUploader();

      _token.success(function(data) {
        $scope.tokenStatus = 'received'
        // Define policy and signature for AWS upload
        token = data;

        // Url to hit for the post request
        uploader.url = token.url;
      })
      .error(function() {
        throw new Error('Couldn\'t retreive AWS credentials');
      })

      // Add the img in session storage once added
      uploader.onAfterAddingFile = function(fileItem) {
        // Updates the formData for Amazon AWS S3 Upload
        fileItem.formData.push({
          key:  fileItem.file.name,
          AWSAccessKeyId: token.AWSKey,
          acl: 'private',
          'Content-Type': (fileItem.file.type !== '') ? fileItem.file.type : 'application/octet-stream',
          filename: fileItem.file.name,
          policy: token.policy,
          signature: token.signature
        });

        if (isFileTooBig)
          return;

        var reader = new FileReader();

        // Turns img into a dataUrl so it can
        // be stored in the session storage
        reader.readAsDataURL(fileItem._file);
        reader.onload = onLoad;

        try {
          $scope.$storage.reader = reader;
        } catch(e) {
          throw new Error(e);
          isFileTooBig = true;
        }

        // To resize the picture we need a hidden canvas
        // to draw a new pic with the expected dimensions
        var canvas = document.createElement('canvas');
        canvas.style.visibility = 'hidden';
        document.body.appendChild(canvas);

        // Wait for the reader to be loaded to get the right img.src
        function onLoad(event) {
          var img = new Image();
          img.onload = utils.getDimensions(canvas, $scope.$storage);
          img.src = event.target.result;
        }
      };

      uploader.onBeforeUploadItem = function(fileItem) {
        // Parse the item stored in session storage
        // before the server upload
        if (!isFileTooBig)
          fileItem._file = utils.dataURItoBlob($scope.$storage.reader);
      };

      uploader.onCompleteItem = function(fileItem, response, status, headers) {
        // Empty the session storage once the item has been uploaded
        delete $scope.$storage.reader;
      };

      uploader.onErrorItem = function(fileItem, response, status, headers) {
        // TODO: try to reupload the img
      };
    }]);

})(angular.module('uploads.controllers', ['token', 'angularFileUpload', 'ngStorage']))
<|endoftext|>


<commit_before>import * as React from 'react'
import * as Immutable from 'immutable'
import Styles from './styles'
import * as Util from './util'

import * as actions from '../actions'

import WindowHeader from './WindowHeader'
import TabItem from './TabItem'

const FilteredTabWindow = React.createClass({
  getInitialState () {
    // Note:  We initialize this with null rather than false so that it will follow
    // open / closed state of window
    return ({ expanded: null })
  },

  componentWillReceiveProps (nextProps) {
    if (nextProps.isSelected && !this.props.isSelected) {
      // If this window becomes selected:
      if (this.windowDivRef) {
        this.windowDivRef.scrollIntoViewIfNeeded()
      }
    }
    if (nextProps.expandAll !== this.props.expandAll) {
      if (this.state.expanded !== null) {
        this.setState({ expanded: null })
      }
    }
  },

  handleOpen () {
    actions.openWindow(this.props.winStore.getCurrentWindow(), this.props.filteredTabWindow.tabWindow, this.props.storeUpdateHandler)
    if (this.props.onItemSelected) {
      this.props.onItemSelected(this.props.filteredTabWindow.tabWindow)
    }
  },

  handleClose (event) { // eslint-disable-line no-unused-vars
    // console.log("handleClose")
    actions.closeWindow(this.props.filteredTabWindow.tabWindow, this.props.storeUpdateHandler)
  },

  handleRevert (event) { // eslint-disable-line no-unused-vars
    var appComponent = this.props.appComponent
    appComponent.openRevertModal(this.props.filteredTabWindow)
  },

  /* expanded state follows window open/closed state unless it is
   * explicitly set interactively by the user
   */
  getExpandedState () {
    if (this.state.expanded === null) {
      return (this.props.expandAll && this.props.filteredTabWindow.tabWindow.open)
    }
    return this.state.expanded
  },

  renderTabItems (tabWindow, tabs) {
    /*
     * We tried explicitly checking for expanded state and
     * returning null if not expanded, but (somewhat surprisingly) it
     * was no faster, even with dozens of hidden tabs
     */
    var items = []
    for (var i = 0; i < tabs.count(); i++) {
      var id = 'tabItem-' + i
      const isSelected = (i === this.props.selectedTabIndex)
      var tabItem = (
        <TabItem
          winStore={this.props.winStore}
          storeUpdateHandler={this.props.storeUpdateHandler}
          tabWindow={tabWindow}
          tab={tabs.get(i)}
          key={id}
          tabIndex={i}
          isSelected={isSelected}
          appComponent={this.props.appComponent}
          onItemSelected={this.props.onItemSelected} />)
      items.push(tabItem)
    }

    var expanded = this.getExpandedState()
    var expandableContentStyle = expanded ? Styles.expandablePanelContentOpen : Styles.expandablePanelContentClosed
    var tabListStyle = Util.merge(Styles.tabList, expandableContentStyle)
    return (

        {items}

)
  },

  handleExpand (expand) {
    this.setState({ expanded: expand })
  },

  render () {
    var filteredTabWindow = this.props.filteredTabWindow
    var tabWindow = filteredTabWindow.tabWindow
    var tabs
    if (this.props.searchStr.length === 0) {
      tabs = tabWindow.tabItems
    } else {
      tabs = filteredTabWindow.itemMatches.map((fti) => fti.tabItem)
    }

    /*
     * optimization:  Let's only render tabItems if expanded
     */
    var expanded = this.getExpandedState()
    var tabItems = null
    if (expanded) {
      tabItems = this.renderTabItems(tabWindow, tabs)
    } else {
      // render empty list of tab items to get -ve margin rollup layout right...
      tabItems = this.renderTabItems(tabWindow, Immutable.Seq())
    }

    var windowHeader = (
      <WindowHeader
        winStore={this.props.winStore}
        storeUpdateHandler={this.props.storeUpdateHandler}
        tabWindow={tabWindow}
        expanded={expanded}
        onExpand={this.handleExpand}
        onOpen={this.handleOpen}
        onRevert={this.handleRevert}
        onClose={this.handleClose}
        appComponent={this.props.appComponent}
        onItemSelected={this.props.onItemSelected} />)

    var selectedStyle = this.props.isSelected ? Styles.tabWindowSelected : null
    var focusedStyle = this.props.isFocused ? Styles.tabWindowFocused : null
    var windowStyles = Util.merge(Styles.tabWindow, Styles.expandablePanel, selectedStyle, focusedStyle)

    var windowDivProps = {
      style: windowStyles,
      onMouseOver: this.handleMouseOver,
      onMouseOut: this.handleMouseOut
    }
    return (

        {windowHeader}
        {tabItems}

      )
  }
})

export default FilteredTabWindow
<commit_msg>Set windowDivRef to div containing the window summary DOM component.  Fixes #85<commit_after>import * as React from 'react'
import * as Immutable from 'immutable'
import Styles from './styles'
import * as Util from './util'

import * as actions from '../actions'

import WindowHeader from './WindowHeader'
import TabItem from './TabItem'

const FilteredTabWindow = React.createClass({
  getInitialState () {
    // Note:  We initialize this with null rather than false so that it will follow
    // open / closed state of window
    return ({ expanded: null })
  },

  componentWillReceiveProps (nextProps) {
    if (nextProps.isSelected && !this.props.isSelected) {
      // If this window becomes selected:
      if (this.windowDivRef) {
        this.windowDivRef.scrollIntoViewIfNeeded()
      }
    }
    if (nextProps.expandAll !== this.props.expandAll) {
      if (this.state.expanded !== null) {
        this.setState({ expanded: null })
      }
    }
  },

  handleOpen () {
    actions.openWindow(this.props.winStore.getCurrentWindow(), this.props.filteredTabWindow.tabWindow, this.props.storeUpdateHandler)
    if (this.props.onItemSelected) {
      this.props.onItemSelected(this.props.filteredTabWindow.tabWindow)
    }
  },

  handleClose (event) { // eslint-disable-line no-unused-vars
    // console.log("handleClose")
    actions.closeWindow(this.props.filteredTabWindow.tabWindow, this.props.storeUpdateHandler)
  },

  handleRevert (event) { // eslint-disable-line no-unused-vars
    var appComponent = this.props.appComponent
    appComponent.openRevertModal(this.props.filteredTabWindow)
  },

  /* expanded state follows window open/closed state unless it is
   * explicitly set interactively by the user
   */
  getExpandedState () {
    if (this.state.expanded === null) {
      return (this.props.expandAll && this.props.filteredTabWindow.tabWindow.open)
    }
    return this.state.expanded
  },

  renderTabItems (tabWindow, tabs) {
    /*
     * We tried explicitly checking for expanded state and
     * returning null if not expanded, but (somewhat surprisingly) it
     * was no faster, even with dozens of hidden tabs
     */
    var items = []
    for (var i = 0; i < tabs.count(); i++) {
      var id = 'tabItem-' + i
      const isSelected = (i === this.props.selectedTabIndex)
      var tabItem = (
        <TabItem
          winStore={this.props.winStore}
          storeUpdateHandler={this.props.storeUpdateHandler}
          tabWindow={tabWindow}
          tab={tabs.get(i)}
          key={id}
          tabIndex={i}
          isSelected={isSelected}
          appComponent={this.props.appComponent}
          onItemSelected={this.props.onItemSelected} />)
      items.push(tabItem)
    }

    var expanded = this.getExpandedState()
    var expandableContentStyle = expanded ? Styles.expandablePanelContentOpen : Styles.expandablePanelContentClosed
    var tabListStyle = Util.merge(Styles.tabList, expandableContentStyle)
    return (

        {items}

)
  },

  handleExpand (expand) {
    this.setState({ expanded: expand })
  },

  render () {
    var filteredTabWindow = this.props.filteredTabWindow
    var tabWindow = filteredTabWindow.tabWindow
    var tabs
    if (this.props.searchStr.length === 0) {
      tabs = tabWindow.tabItems
    } else {
      tabs = filteredTabWindow.itemMatches.map((fti) => fti.tabItem)
    }

    /*
     * optimization:  Let's only render tabItems if expanded
     */
    var expanded = this.getExpandedState()
    var tabItems = null
    if (expanded) {
      tabItems = this.renderTabItems(tabWindow, tabs)
    } else {
      // render empty list of tab items to get -ve margin rollup layout right...
      tabItems = this.renderTabItems(tabWindow, Immutable.Seq())
    }

    var windowHeader = (
      <WindowHeader
        winStore={this.props.winStore}
        storeUpdateHandler={this.props.storeUpdateHandler}
        tabWindow={tabWindow}
        expanded={expanded}
        onExpand={this.handleExpand}
        onOpen={this.handleOpen}
        onRevert={this.handleRevert}
        onClose={this.handleClose}
        appComponent={this.props.appComponent}
        onItemSelected={this.props.onItemSelected} />)

    var selectedStyle = this.props.isSelected ? Styles.tabWindowSelected : null
    var focusedStyle = this.props.isFocused ? Styles.tabWindowFocused : null
    var windowStyles = Util.merge(Styles.tabWindow, Styles.expandablePanel, selectedStyle, focusedStyle)

    var windowDivProps = {
      style: windowStyles,
      onMouseOver: this.handleMouseOver,
      onMouseOut: this.handleMouseOut,
      ref: wdiv => { this.windowDivRef = wdiv }
    }
    return (

        {windowHeader}
        {tabItems}

    )
  }
})

export default FilteredTabWindow
<|endoftext|>


<commit_before>import update from 'immutability-helper';

import { default as api } from '../utils/api';

// ------------------------------------
// Constants
// ------------------------------------
export const RECEIVE_ATTRIBUTE_TYPES = 'ui/RECEIVE_ATTRIBUTE_TYPES';

export const CLOSE_MESSAGE = 'ui/CLOSE_MESSAGE';
export const DISPLAY_MESSAGE = 'ui/DISPLAY_MESSAGE';

// ------------------------------------
// Actions
// ------------------------------------
export function receiveAttributeTypes (attributes, validationRules) {
  const attributeTypeList = {};
  attributes.results.map(result => {
    if (result.values) {
      let required = false;
      let requiredIn = [];
      let requiredIf = [];

      // Add basic required if so
      validationRules.record.required.map(rule => {
        if (rule === result.identifier) {
          required = true;
        }
      });

      Object.keys(validationRules).map(key => {
        validationRules[key].required && validationRules[key].required.map(rule => {
          if (rule === result.identifier) {
            requiredIn.push(key);
          }
        });
      });

      Object.keys(validationRules).map(key => {
        validationRules[key].allOf && validationRules[key].allOf.map(rule => {
          // TODO: add rules
        });
      });

      attributeTypeList[result.identifier] = {
        name: result.name,
        values: result.values,
        requiredIf,
        requiredIn,
        required
      };
    }
  });
  return {
    type: RECEIVE_ATTRIBUTE_TYPES,
    attributeTypeList
  };
}

export function displayMessage (message) {
  return {
    type: DISPLAY_MESSAGE,
    message
  };
}

export function closeMessage () {
  return {
    type: CLOSE_MESSAGE
  };
}

export function fetchAttributeTypes () {
  return function (dispatch) {
    return api.get('attribute/schemas')
      .then(response => response.json())
      .then(validationRules => {
        return api.get('attribute')
          .then(response => response.json())
          .then(json =>
            dispatch(receiveAttributeTypes(json, validationRules)));
      });
  };
}

export const actions = {
  closeMessage,
  fetchAttributeTypes,
  receiveAttributeTypes
};

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [RECEIVE_ATTRIBUTE_TYPES]: (state, action) => {
    const recordTypes = action.attributeTypeList.RecordType;
    const recordTypeList = {};
    recordTypes.values.map(result => {
      const trimmedResult = result.id.replace(/-/g, '');
      recordTypeList[trimmedResult] = result.value;
    });
    delete action.attributeTypeList.RecordType;
    return update(state, {
      attributeTypes: { $set: action.attributeTypeList },
      recordTypes: { $set: recordTypeList }
    });
  },
  [DISPLAY_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: true },
        text: { $set: action.message.text },
        success: { $set: action.message.success }
      }
    });
  },
  [CLOSE_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: false },
        text: { $set: '' },
        success: { $set: false }
      }
    });
  }
};

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  isFetching: false,
  recordTypes: {},
  attributeTypes: {},
  message: {
    active: false,
    text: '',
    success: false
  }
};

export default function uiReducer (state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type];
  return handler ? handler(state, action) : state;
}
<commit_msg>Add requiredIn attribute<commit_after>import update from 'immutability-helper';

import { default as api } from '../utils/api';

// ------------------------------------
// Constants
// ------------------------------------
export const RECEIVE_ATTRIBUTE_TYPES = 'ui/RECEIVE_ATTRIBUTE_TYPES';

export const CLOSE_MESSAGE = 'ui/CLOSE_MESSAGE';
export const DISPLAY_MESSAGE = 'ui/DISPLAY_MESSAGE';

// ------------------------------------
// Actions
// ------------------------------------
export function receiveAttributeTypes (attributes, validationRules) {
  const attributeTypeList = {};
  attributes.results.map(result => {
    if (result.values) {
      let required = false;
      let requiredIn = [];
      let requiredIf = [];

      // Add basic required if so
      validationRules.record.required.map(rule => {
        if (rule === result.identifier) {
          required = true;
        }
      });

      // Add requiredIn attributes
      Object.keys(validationRules).map(key => {
        validationRules[key].required && validationRules[key].required.map(rule => {
          if (rule === result.identifier) {
            requiredIn.push(key);
          }
        });
      });

      Object.keys(validationRules).map(key => {
        validationRules[key].allOf && validationRules[key].allOf.map(rule => {
          // TODO: add rules
        });
      });

      attributeTypeList[result.identifier] = {
        name: result.name,
        values: result.values,
        requiredIf,
        requiredIn,
        required
      };
    }
  });
  return {
    type: RECEIVE_ATTRIBUTE_TYPES,
    attributeTypeList
  };
}

export function displayMessage (message) {
  return {
    type: DISPLAY_MESSAGE,
    message
  };
}

export function closeMessage () {
  return {
    type: CLOSE_MESSAGE
  };
}

export function fetchAttributeTypes () {
  return function (dispatch) {
    return api.get('attribute/schemas')
      .then(response => response.json())
      .then(validationRules => {
        return api.get('attribute')
          .then(response => response.json())
          .then(json =>
            dispatch(receiveAttributeTypes(json, validationRules)));
      });
  };
}

export const actions = {
  closeMessage,
  fetchAttributeTypes,
  receiveAttributeTypes
};

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [RECEIVE_ATTRIBUTE_TYPES]: (state, action) => {
    const recordTypes = action.attributeTypeList.RecordType;
    const recordTypeList = {};
    recordTypes.values.map(result => {
      const trimmedResult = result.id.replace(/-/g, '');
      recordTypeList[trimmedResult] = result.value;
    });
    delete action.attributeTypeList.RecordType;
    return update(state, {
      attributeTypes: { $set: action.attributeTypeList },
      recordTypes: { $set: recordTypeList }
    });
  },
  [DISPLAY_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: true },
        text: { $set: action.message.text },
        success: { $set: action.message.success }
      }
    });
  },
  [CLOSE_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: false },
        text: { $set: '' },
        success: { $set: false }
      }
    });
  }
};

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  isFetching: false,
  recordTypes: {},
  attributeTypes: {},
  message: {
    active: false,
    text: '',
    success: false
  }
};

export default function uiReducer (state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type];
  return handler ? handler(state, action) : state;
}
<|endoftext|>


<commit_before>import classNames from "classnames";
import deepEqual from "deep-equal";
import React from "react";

import Chart from "./Chart";
import DialChart from "./DialChart";

const TASKS_PER_ROW = 3;
const TASK_INFO = {
  TASK_RUNNING: { label: "任务运行", colorIndex: 4 },
  TASK_STAGING: { label: "任务暂存", colorIndex: 1 }
};
const DISPLAYED_TASK_KEYS = Object.keys(TASK_INFO);

function getEmptyTaskData() {
  return DISPLAYED_TASK_KEYS.map(function(key) {
    return {
      name: key,
      colorIndex: TASK_INFO[key].colorIndex,
      value: 0
    };
  });
}

var TasksChart = React.createClass({
  displayName: "TasksChart",

  propTypes: {
    // {TASK_RUNNING: 0, TASK_STAGING: 4}
    tasks: React.PropTypes.object.isRequired
  },

  shouldComponentUpdate(nextProps) {
    var previousTasks = this.getTasks(this.props.tasks);
    var newTasks = this.getTasks(nextProps.tasks);

    // If equal, do not update
    return !deepEqual(previousTasks, newTasks);
  },

  getTaskInfo(tasks) {
    if (tasks.length === 0) {
      tasks = getEmptyTaskData();
    }

    var numberOfTasks = DISPLAYED_TASK_KEYS.length;

    return DISPLAYED_TASK_KEYS.map(function(key) {
      const info = TASK_INFO[key];
      var task = tasks.find(function(task) {
        return task.name === key;
      });
      if (task === undefined) {
        task = { value: 0 };
      }
      var classes = {
        "unit-bordered-horizontal-small text-align-center column-12": true
      };
      // equalize columns for units
      if (numberOfTasks > TASKS_PER_ROW) {
        classes["column-small-4"] = true;
      } else {
        classes["column-small-" + 12 / numberOfTasks] = true;
      }
      var classSet = classNames(classes);

      return (

            {task.value}

            {info.label}

      );
    });
  },

  getTotal(tasks) {
    return tasks.reduce(function(acc, task) {
      return acc + task.value;
    }, 0);
  },

  getTasks(tasks = {}) {
    return DISPLAYED_TASK_KEYS.map(function(key) {
      return {
        colorIndex: TASK_INFO[key].colorIndex,
        name: key,
        value: tasks[key]
      };
    });
  },

  getDialChart(tasks) {
    var total = this.getTotal(tasks);

    if (tasks.length === 0) {
      tasks = getEmptyTaskData();
    }

    return (
      <DialChart data={tasks} slices={getEmptyTaskData()}>
        {this.getDialChartChildren(total)}
      </DialChart>
    );
  },

  getDialChartChildren(total) {
    return (

        {total}
        总任务

    );
  },

  render() {
    var tasks = this.getTasks(this.props.tasks);

    return (

        <Chart>
          {this.getDialChart(tasks)}
        </Chart>

          {this.getTaskInfo(tasks)}

    );
  }
});

module.exports = TasksChart;
<commit_msg>Dashboard  仪表盘页面汉化--任务暂停<commit_after>import classNames from "classnames";
import deepEqual from "deep-equal";
import React from "react";

import Chart from "./Chart";
import DialChart from "./DialChart";

const TASKS_PER_ROW = 3;
const TASK_INFO = {
  TASK_RUNNING: { label: "任务运行", colorIndex: 4 },
  TASK_STAGING: { label: "任务暂停", colorIndex: 1 }
};
const DISPLAYED_TASK_KEYS = Object.keys(TASK_INFO);

function getEmptyTaskData() {
  return DISPLAYED_TASK_KEYS.map(function(key) {
    return {
      name: key,
      colorIndex: TASK_INFO[key].colorIndex,
      value: 0
    };
  });
}

var TasksChart = React.createClass({
  displayName: "TasksChart",

  propTypes: {
    // {TASK_RUNNING: 0, TASK_STAGING: 4}
    tasks: React.PropTypes.object.isRequired
  },

  shouldComponentUpdate(nextProps) {
    var previousTasks = this.getTasks(this.props.tasks);
    var newTasks = this.getTasks(nextProps.tasks);

    // If equal, do not update
    return !deepEqual(previousTasks, newTasks);
  },

  getTaskInfo(tasks) {
    if (tasks.length === 0) {
      tasks = getEmptyTaskData();
    }

    var numberOfTasks = DISPLAYED_TASK_KEYS.length;

    return DISPLAYED_TASK_KEYS.map(function(key) {
      const info = TASK_INFO[key];
      var task = tasks.find(function(task) {
        return task.name === key;
      });
      if (task === undefined) {
        task = { value: 0 };
      }
      var classes = {
        "unit-bordered-horizontal-small text-align-center column-12": true
      };
      // equalize columns for units
      if (numberOfTasks > TASKS_PER_ROW) {
        classes["column-small-4"] = true;
      } else {
        classes["column-small-" + 12 / numberOfTasks] = true;
      }
      var classSet = classNames(classes);

      return (

            {task.value}

            {info.label}

      );
    });
  },

  getTotal(tasks) {
    return tasks.reduce(function(acc, task) {
      return acc + task.value;
    }, 0);
  },

  getTasks(tasks = {}) {
    return DISPLAYED_TASK_KEYS.map(function(key) {
      return {
        colorIndex: TASK_INFO[key].colorIndex,
        name: key,
        value: tasks[key]
      };
    });
  },

  getDialChart(tasks) {
    var total = this.getTotal(tasks);

    if (tasks.length === 0) {
      tasks = getEmptyTaskData();
    }

    return (
      <DialChart data={tasks} slices={getEmptyTaskData()}>
        {this.getDialChartChildren(total)}
      </DialChart>
    );
  },

  getDialChartChildren(total) {
    return (

        {total}
        总任务

    );
  },

  render() {
    var tasks = this.getTasks(this.props.tasks);

    return (

        <Chart>
          {this.getDialChart(tasks)}
        </Chart>

          {this.getTaskInfo(tasks)}

    );
  }
});

module.exports = TasksChart;
<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch';
import update from 'immutability-helper';

import { getApiUrl } from '../utils/helpers';

// ------------------------------------
// Constants
// ------------------------------------
export const RECEIVE_RECORDTYPES = 'ui/RECEIVE_RECORDTYPES';
export const RECEIVE_ATTRIBUTE_TYPES = 'ui/RECEIVE_ATTRIBUTE_TYPES';

export const CLOSE_MESSAGE = 'ui/CLOSE_MESSAGE';
export const DISPLAY_MESSAGE = 'ui/DISPLAY_MESSAGE';

// ------------------------------------
// Actions
// ------------------------------------
export function receiveRecordTypes (recordTypes) {
  const recordTypeList = {};
  recordTypes.results.map(result => {
    const trimmedResult = result.id.replace(/-/g, '');
    recordTypeList[trimmedResult] = result.value;
  });
  return {
    type: RECEIVE_RECORDTYPES,
    recordTypeList
  };
}

export function receiveAttributeTypes (attributes, validationRules) {
  const attributeTypeList = {};
  attributes.results.map(result => {
    if (result.values) {
      let required;
      validationRules.record.required.map(rule => {
        if (rule === result.identifier) {
          required = true;
        }
      });
      if (required !== true) {
        required = false;
      }
      attributeTypeList[result.identifier] = {
        name: result.name,
        values: result.values,
        required
      };
    }
  });
  return {
    type: RECEIVE_ATTRIBUTE_TYPES,
    attributeTypeList
  };
}

export function displayMessage (message) {
  return {
    type: DISPLAY_MESSAGE,
    message
  };
}

export function closeMessage () {
  return {
    type: CLOSE_MESSAGE
  };
}

export function fetchAttributeTypes () {
  return function (dispatch) {
    return fetch(getApiUrl('attribute/schemas'))
      .then(response => response.json())
      .then(validationRules => {
        return fetch(getApiUrl('attribute'))
          .then(response => response.json())
          .then(json =>
            dispatch(receiveAttributeTypes(json, validationRules)));
      });
  };
}

export const actions = {
  receiveAttributeTypes,
  closeMessage,
  fetchAttributeTypes
};

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [RECEIVE_ATTRIBUTE_TYPES]: (state, action) => {
    const recordTypes = action.attributeTypeList.RecordType;
    const recordTypeList = {};
    recordTypes.values.map(result => {
      const trimmedResult = result.id.replace(/-/g, '');
      recordTypeList[trimmedResult] = result.value;
    });
    delete action.attributeTypeList.RecordType;
    return update(state, {
      attributeTypes: { $set: action.attributeTypeList },
      recordTypes: { $set: recordTypeList }
    });
  },
  [DISPLAY_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: true },
        text: { $set: action.message },
        success: { $set: true }
      }
    });
  },
  [CLOSE_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: false },
        text: { $set: '' },
        success: { $set: false }
      }
    });
  }
};

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  isFetching: false,
  recordTypes: {},
  attributeTypes: {},
  message: {
    active: false,
    text: '',
    success: false
  }
};

export default function uiReducer (state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type];
  return handler ? handler(state, action) : state;
}
<commit_msg>Remove redundand methods from uiReducer<commit_after>import fetch from 'isomorphic-fetch';
import update from 'immutability-helper';

import { getApiUrl } from '../utils/helpers';

// ------------------------------------
// Constants
// ------------------------------------
export const RECEIVE_ATTRIBUTE_TYPES = 'ui/RECEIVE_ATTRIBUTE_TYPES';

export const CLOSE_MESSAGE = 'ui/CLOSE_MESSAGE';
export const DISPLAY_MESSAGE = 'ui/DISPLAY_MESSAGE';

// ------------------------------------
// Actions
// ------------------------------------
export function receiveAttributeTypes (attributes, validationRules) {
  const attributeTypeList = {};
  attributes.results.map(result => {
    if (result.values) {
      let required;
      validationRules.record.required.map(rule => {
        if (rule === result.identifier) {
          required = true;
        }
      });
      if (required !== true) {
        required = false;
      }
      attributeTypeList[result.identifier] = {
        name: result.name,
        values: result.values,
        required
      };
    }
  });
  return {
    type: RECEIVE_ATTRIBUTE_TYPES,
    attributeTypeList
  };
}

export function displayMessage (message) {
  return {
    type: DISPLAY_MESSAGE,
    message
  };
}

export function closeMessage () {
  return {
    type: CLOSE_MESSAGE
  };
}

export function fetchAttributeTypes () {
  return function (dispatch) {
    return fetch(getApiUrl('attribute/schemas'))
      .then(response => response.json())
      .then(validationRules => {
        return fetch(getApiUrl('attribute'))
          .then(response => response.json())
          .then(json =>
            dispatch(receiveAttributeTypes(json, validationRules)));
      });
  };
}

export const actions = {
  closeMessage,
  fetchAttributeTypes,
  receiveAttributeTypes
};

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [RECEIVE_ATTRIBUTE_TYPES]: (state, action) => {
    const recordTypes = action.attributeTypeList.RecordType;
    const recordTypeList = {};
    recordTypes.values.map(result => {
      const trimmedResult = result.id.replace(/-/g, '');
      recordTypeList[trimmedResult] = result.value;
    });
    delete action.attributeTypeList.RecordType;
    return update(state, {
      attributeTypes: { $set: action.attributeTypeList },
      recordTypes: { $set: recordTypeList }
    });
  },
  [DISPLAY_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: true },
        text: { $set: action.message },
        success: { $set: true }
      }
    });
  },
  [CLOSE_MESSAGE]: (state, action) => {
    return update(state, {
      message: {
        active: { $set: false },
        text: { $set: '' },
        success: { $set: false }
      }
    });
  }
};

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  isFetching: false,
  recordTypes: {},
  attributeTypes: {},
  message: {
    active: false,
    text: '',
    success: false
  }
};

export default function uiReducer (state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type];
  return handler ? handler(state, action) : state;
}
<|endoftext|>


<commit_before>/**
 * @flow
 */

import type {StylesheetSpec} from './Stylesheet';

import prefix from 'inline-style-prefix-all';
import createHash from 'murmurhash-js/murmurhash3_gc';
import CSSProperty from 'react/lib/CSSProperty';
import hyphenateStyleName from 'fbjs/lib/hyphenateStyleName';
import memoizeStringOnly from 'fbjs/lib/memoizeStringOnly';

export type ClassNameMapping = {
  className: string;
  then?: {[name: string]: ClassNameMapping};
};

export type CompileResult = {
  id: string;
  css: string;
  mapping: ClassNameMapping;
};

const UNITLESS_NUMBER = CSSProperty.isUnitlessNumber;

export const PSEUDO_CLASS = {
  focus: true,
  hover: true,
  active: true,
  checked: true,
  default: true,
  disabled: true,
  empty: true,
  enabled: true,
  firstChild: true,
  firstOfType: true,
  fullscreen: true,
  indeterminate: true,
  invalid: true,
  lastChild: true,
  lastOfType: true,
  left: true,
  link: true,
  onlyChild: true,
  optional: true,
  required: true,
  right: true,
  root: true,
  scope: true,
  target: true,
  valid: true,
  visited: true,
};

export default function compile(
  name: string,
  stylesheet: StylesheetSpec
): CompileResult {

  let id = createHash(JSON.stringify(stylesheet));
  let mapping = {};
  let css = [];

  // If base is not defined we need to define it so defaults style kicks in.
  if (stylesheet.base == null) {
    stylesheet = {
      base: {},
      ...stylesheet,
    };
  }

  for (let variant in stylesheet) {

    let style = stylesheet[variant];
    if (variant.indexOf('_') > -1) {
      variant = variant.split('_');
    } else {
      variant = [variant];
    }
    variant.sort();

    let seenPseudoClass = false;
    let trace = [name];
    let variantMapping = mapping;
    for (let i = 0; i < variant.length; i++) {
      if (variant[i] === 'base' && variant.length > 1) {
        throw new Error('"base" should not be used as a part of a complex variant');
      }

      if (variant[i] !== 'base' && !seenPseudoClass) {
        variantMapping.then = variantMapping.then || {};
        variantMapping.then[variant[i]] = variantMapping.then[variant[i]] || {};
        variantMapping = variantMapping.then[variant[i]];
        trace.push(variant[i]);
      }

      if (i === variant.length - 1) {
        if (variant[i] === 'base') {
          style = {boxSizing: 'border-box', ...style};
        }
        let className = `${trace.join('-')}-${id}`;
        css.push(compileStyle(className, style));
        variantMapping.className = className;
      }
    }

  }

  return {id, css: css.join('\n'), mapping};
}

function compileStyle(className, style) {
  let css = [];
  let cssList = [];
  let ownStyle = {};

  for (let name in style) {
    let value = style[name];
    if (!style.hasOwnProperty(name)) {
      continue;
    }
    if (PSEUDO_CLASS.hasOwnProperty(name) && PSEUDO_CLASS[name]) {
      // this is pseudo class, recurse
      cssList.push(compileStyle(className + ':' + compileName(name), value));
    } else if (!isEmpty(value)) {
      ownStyle[name] = value;
    }
  }

  ownStyle = prefix(ownStyle);

  for (let name in ownStyle) {
    let value = ownStyle[name];
    let cssName = compileName(name);
    if (Array.isArray(value)) {
      for (let i = 0; i < value.length; i++) {
        let cssValue = compileValue(name, value[i]);
        css.push(`${cssName}:${cssValue}`);
      }
    } else {
      let cssValue = compileValue(name, value);
      css.push(`${cssName}:${cssValue}`);
    }
  }

  if (css.length > 0) {
    return [`.${className} { ${css.join(';')}; }`].concat(cssList).join('\n');
  } else {
    return cssList.join('\n');
  }
}

function isEmpty(value) {
  return (
    value == null ||
    value === '' ||
    value === false
  );
}

/**
 * Compile style prop name.
 *
 * Based on code in React, see react/lib/CSSPropertyOperations module.
 */
let compileName = memoizeStringOnly(name => hyphenateStyleName(name));

/**
 * Compile style prop value.
 *
 * Based on code in React, see react/lib/dangerousStyleValue module.
 */
function compileValue(name: string, value: mixed): string {
  let isNonNumeric = isNaN(value);
  if (
    isNonNumeric ||
    value === 0 ||
    UNITLESS_NUMBER.hasOwnProperty(name) && UNITLESS_NUMBER[name]
  ) {
    return '' + ((value: any): string); // cast to string
  } else {
    return ((value: any): string) + 'px';
  }
}
<commit_msg>fix: do not compile left/right as prop sets<commit_after>/**
 * @flow
 */

import type {StylesheetSpec} from './Stylesheet';

import prefix from 'inline-style-prefix-all';
import createHash from 'murmurhash-js/murmurhash3_gc';
import CSSProperty from 'react/lib/CSSProperty';
import hyphenateStyleName from 'fbjs/lib/hyphenateStyleName';
import memoizeStringOnly from 'fbjs/lib/memoizeStringOnly';

export type ClassNameMapping = {
  className: string;
  then?: {[name: string]: ClassNameMapping};
};

export type CompileResult = {
  id: string;
  css: string;
  mapping: ClassNameMapping;
};

const UNITLESS_NUMBER = CSSProperty.isUnitlessNumber;

export const PSEUDO_CLASS = {
  focus: true,
  hover: true,
  active: true,
  checked: true,
  default: true,
  disabled: true,
  empty: true,
  enabled: true,
  firstChild: true,
  firstOfType: true,
  fullscreen: true,
  indeterminate: true,
  invalid: true,
  lastChild: true,
  lastOfType: true,
  link: true,
  onlyChild: true,
  optional: true,
  required: true,
  root: true,
  scope: true,
  target: true,
  valid: true,
  visited: true,
};

export default function compile(
  name: string,
  stylesheet: StylesheetSpec
): CompileResult {

  let id = createHash(JSON.stringify(stylesheet));
  let mapping = {};
  let css = [];

  // If base is not defined we need to define it so defaults style kicks in.
  if (stylesheet.base == null) {
    stylesheet = {
      base: {},
      ...stylesheet,
    };
  }

  for (let variant in stylesheet) {

    let style = stylesheet[variant];
    if (variant.indexOf('_') > -1) {
      variant = variant.split('_');
    } else {
      variant = [variant];
    }
    variant.sort();

    let seenPseudoClass = false;
    let trace = [name];
    let variantMapping = mapping;
    for (let i = 0; i < variant.length; i++) {
      if (variant[i] === 'base' && variant.length > 1) {
        throw new Error('"base" should not be used as a part of a complex variant');
      }

      if (variant[i] !== 'base' && !seenPseudoClass) {
        variantMapping.then = variantMapping.then || {};
        variantMapping.then[variant[i]] = variantMapping.then[variant[i]] || {};
        variantMapping = variantMapping.then[variant[i]];
        trace.push(variant[i]);
      }

      if (i === variant.length - 1) {
        if (variant[i] === 'base') {
          style = {boxSizing: 'border-box', ...style};
        }
        let className = `${trace.join('-')}-${id}`;
        css.push(compileStyle(className, style));
        variantMapping.className = className;
      }
    }

  }

  return {id, css: css.join('\n'), mapping};
}

function compileStyle(className, style) {
  let css = [];
  let cssList = [];
  let ownStyle = {};

  for (let name in style) {
    let value = style[name];
    if (!style.hasOwnProperty(name)) {
      continue;
    }
    if (PSEUDO_CLASS.hasOwnProperty(name) && PSEUDO_CLASS[name]) {
      // this is pseudo class, recurse
      cssList.push(compileStyle(className + ':' + compileName(name), value));
    } else if (!isEmpty(value)) {
      ownStyle[name] = value;
    }
  }

  ownStyle = prefix(ownStyle);

  for (let name in ownStyle) {
    let value = ownStyle[name];
    let cssName = compileName(name);
    if (Array.isArray(value)) {
      for (let i = 0; i < value.length; i++) {
        let cssValue = compileValue(name, value[i]);
        css.push(`${cssName}:${cssValue}`);
      }
    } else {
      let cssValue = compileValue(name, value);
      css.push(`${cssName}:${cssValue}`);
    }
  }

  if (css.length > 0) {
    return [`.${className} { ${css.join(';')}; }`].concat(cssList).join('\n');
  } else {
    return cssList.join('\n');
  }
}

function isEmpty(value) {
  return (
    value == null ||
    value === '' ||
    value === false
  );
}

/**
 * Compile style prop name.
 *
 * Based on code in React, see react/lib/CSSPropertyOperations module.
 */
let compileName = memoizeStringOnly(name => hyphenateStyleName(name));

/**
 * Compile style prop value.
 *
 * Based on code in React, see react/lib/dangerousStyleValue module.
 */
function compileValue(name: string, value: mixed): string {
  let isNonNumeric = isNaN(value);
  if (
    isNonNumeric ||
    value === 0 ||
    UNITLESS_NUMBER.hasOwnProperty(name) && UNITLESS_NUMBER[name]
  ) {
    return '' + ((value: any): string); // cast to string
  } else {
    return ((value: any): string) + 'px';
  }
}
<|endoftext|>


<commit_before>(function () {
  var ns = $.namespace('pskl.controller');

  ns.PaletteController = function () {};

  /**
   * @public
   */
  ns.PaletteController.prototype.init = function() {
    $.subscribe(Events.SELECT_PRIMARY_COLOR, this.onColorSelected_.bind(this, {isPrimary : true}));
    $.subscribe(Events.SELECT_SECONDARY_COLOR, this.onColorSelected_.bind(this, {isPrimary : false}));

    var shortcuts = pskl.service.keyboard.Shortcuts;
    pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.SWAP, this.swapColors.bind(this));
    pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.RESET, this.resetColors.bind(this));

    var spectrumCfg = {
      showPalette: true,
      showButtons: false,
      showInput: true,
      palette: [
        ['rgba(0,0,0,0)']
      ],
      clickoutFiresChange : true,

      beforeShow : function(tinycolor) {
        tinycolor.setAlpha(1);
      }
    };

    // Initialize colorpickers:
    var colorPicker = $('#color-picker');
    colorPicker.spectrum($.extend({color: Constants.DEFAULT_PEN_COLOR}, spectrumCfg));
    colorPicker.change({isPrimary : true}, $.proxy(this.onPickerChange_, this));
    this.setTitleOnPicker_(Constants.DEFAULT_PEN_COLOR, colorPicker);

    var secondaryColorPicker = $('#secondary-color-picker');
    secondaryColorPicker.spectrum($.extend({color: Constants.TRANSPARENT_COLOR}, spectrumCfg));
    secondaryColorPicker.change({isPrimary : false}, $.proxy(this.onPickerChange_, this));
    this.setTitleOnPicker_(Constants.TRANSPARENT_COLOR, secondaryColorPicker);

    var swapColorsIcon = $('.swap-colors-button');
    swapColorsIcon.click(this.swapColors.bind(this));
  };

  /**
   * @private
   */
  ns.PaletteController.prototype.onPickerChange_ = function(evt, isPrimary) {
    var inputPicker = $(evt.target);
    if (evt.data.isPrimary) {
      this.setPrimaryColor_(inputPicker.val());
    } else {
      this.setSecondaryColor_(inputPicker.val());
    }
  };

  /**
   * @private
   */
  ns.PaletteController.prototype.onColorSelected_ = function(args, evt, color) {
    var inputPicker = $(evt.target);
    if (args.isPrimary) {
      this.setPrimaryColor_(color);
    } else {
      this.setSecondaryColor_(color);
    }
  };

  ns.PaletteController.prototype.setPrimaryColor_ = function (color) {
    this.updateColorPicker_(color, $('#color-picker'));
    $.publish(Events.PRIMARY_COLOR_SELECTED, [color]);
  };

  ns.PaletteController.prototype.setSecondaryColor_ = function (color) {
    this.updateColorPicker_(color, $('#secondary-color-picker'));
    $.publish(Events.SECONDARY_COLOR_SELECTED, [color]);
  };

  ns.PaletteController.prototype.swapColors = function () {
    var primaryColor = pskl.app.selectedColorsService.getPrimaryColor();
    this.setPrimaryColor_(pskl.app.selectedColorsService.getSecondaryColor());
    this.setSecondaryColor_(primaryColor);
  };

  ns.PaletteController.prototype.resetColors = function () {
    pskl.app.selectedColorsService.reset();
  };

  /**
   * @private
   */
  ns.PaletteController.prototype.updateColorPicker_ = function (color, colorPicker) {
    if (color == Constants.TRANSPARENT_COLOR) {
      // We can set the current palette color to transparent.
      // You can then combine this transparent color with an advanced
      // tool for customized deletions.
      // Eg: bucket + transparent: Delete a colored area
      //     Stroke + transparent: hollow out the equivalent of a stroke

      // The colorpicker can't be set to a transparent state.
      // We set its background to white and insert the
      // string "TRANSPARENT" to mimic this state:
      colorPicker.spectrum('set', Constants.TRANSPARENT_COLOR);
      colorPicker.val(Constants.TRANSPARENT_COLOR);
    } else {
      colorPicker.spectrum('set', color);
    }
    this.setTitleOnPicker_(color, colorPicker);
  };

  ns.PaletteController.prototype.setTitleOnPicker_ = function (title, colorPicker) {
    var parent = colorPicker.parent();
    title = parent.data('initial-title') + '
' + title;
    parent.attr('data-original-title', title);
  };
})();
<commit_msg>Issue #458: format selected color from spectrum  as HexString<commit_after>(function () {
  var ns = $.namespace('pskl.controller');

  ns.PaletteController = function () {};

  /**
   * @public
   */
  ns.PaletteController.prototype.init = function() {
    $.subscribe(Events.SELECT_PRIMARY_COLOR, this.onColorSelected_.bind(this, {isPrimary : true}));
    $.subscribe(Events.SELECT_SECONDARY_COLOR, this.onColorSelected_.bind(this, {isPrimary : false}));

    var shortcuts = pskl.service.keyboard.Shortcuts;
    pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.SWAP, this.swapColors.bind(this));
    pskl.app.shortcutService.registerShortcut(shortcuts.COLOR.RESET, this.resetColors.bind(this));

    var spectrumCfg = {
      showPalette: true,
      showButtons: false,
      showInput: true,
      palette: [
        ['rgba(0,0,0,0)']
      ],
      clickoutFiresChange : true,

      beforeShow : function(tinycolor) {
        tinycolor.setAlpha(1);
      }
    };

    // Initialize colorpickers:
    var colorPicker = $('#color-picker');
    colorPicker.spectrum($.extend({color: Constants.DEFAULT_PEN_COLOR}, spectrumCfg));
    colorPicker.change({isPrimary : true}, $.proxy(this.onPickerChange_, this));
    this.setTitleOnPicker_(Constants.DEFAULT_PEN_COLOR, colorPicker);

    var secondaryColorPicker = $('#secondary-color-picker');
    secondaryColorPicker.spectrum($.extend({color: Constants.TRANSPARENT_COLOR}, spectrumCfg));
    secondaryColorPicker.change({isPrimary : false}, $.proxy(this.onPickerChange_, this));
    this.setTitleOnPicker_(Constants.TRANSPARENT_COLOR, secondaryColorPicker);

    var swapColorsIcon = $('.swap-colors-button');
    swapColorsIcon.click(this.swapColors.bind(this));
  };

  /**
   * @private
   */
  ns.PaletteController.prototype.onPickerChange_ = function(evt, isPrimary) {
    var inputPicker = $(evt.target);
    var color = inputPicker.val();

    if (color != Constants.TRANSPARENT_COLOR) {
      // Unless the color is TRANSPARENT_COLOR, format it to hexstring, as
      // expected by the rest of the application.
      color = window.tinycolor(color).toHexString();
    }

    if (evt.data.isPrimary) {
      this.setPrimaryColor_(color);
    } else {
      this.setSecondaryColor_(color);
    }
  };

  /**
   * @private
   */
  ns.PaletteController.prototype.onColorSelected_ = function(args, evt, color) {
    var inputPicker = $(evt.target);
    if (args.isPrimary) {
      this.setPrimaryColor_(color);
    } else {
      this.setSecondaryColor_(color);
    }
  };

  ns.PaletteController.prototype.setPrimaryColor_ = function (color) {
    this.updateColorPicker_(color, $('#color-picker'));
    $.publish(Events.PRIMARY_COLOR_SELECTED, [color]);
  };

  ns.PaletteController.prototype.setSecondaryColor_ = function (color) {
    this.updateColorPicker_(color, $('#secondary-color-picker'));
    $.publish(Events.SECONDARY_COLOR_SELECTED, [color]);
  };

  ns.PaletteController.prototype.swapColors = function () {
    var primaryColor = pskl.app.selectedColorsService.getPrimaryColor();
    this.setPrimaryColor_(pskl.app.selectedColorsService.getSecondaryColor());
    this.setSecondaryColor_(primaryColor);
  };

  ns.PaletteController.prototype.resetColors = function () {
    pskl.app.selectedColorsService.reset();
  };

  /**
   * @private
   */
  ns.PaletteController.prototype.updateColorPicker_ = function (color, colorPicker) {
    if (color == Constants.TRANSPARENT_COLOR) {
      // We can set the current palette color to transparent.
      // You can then combine this transparent color with an advanced
      // tool for customized deletions.
      // Eg: bucket + transparent: Delete a colored area
      //     Stroke + transparent: hollow out the equivalent of a stroke

      // The colorpicker can't be set to a transparent state.
      // We set its background to white and insert the
      // string "TRANSPARENT" to mimic this state:
      colorPicker.spectrum('set', Constants.TRANSPARENT_COLOR);
      colorPicker.val(Constants.TRANSPARENT_COLOR);
    } else {
      colorPicker.spectrum('set', color);
    }
    this.setTitleOnPicker_(color, colorPicker);
  };

  ns.PaletteController.prototype.setTitleOnPicker_ = function (title, colorPicker) {
    var parent = colorPicker.parent();
    title = parent.data('initial-title') + '
' + title;
    parent.attr('data-original-title', title);
  };
})();
<|endoftext|>


<commit_before>/* eslint-disable import/no-unresolved, import/extensions */
import { StyleSheet } from 'react-native';
/* eslint-enable import/no-unresolved, import/extensions */

import Color from 'color';
import merge from 'lodash.merge';

import { fontWeight } from './typography';
import {
  black, grey100, grey500, white, transparent,
} from './colors';

import lightTheme from './themes/light';
import getPlatformElevation from './getPlatformElevation';

function darkenOrLighten(color, ratio = 0.15) {
    const c = Color(color);
    return c.luminosity() > 0.5 ? c.darken(ratio) : c.lighten(ratio);
}

export default function getTheme(theme, ...more) {
    theme = merge(lightTheme, theme, ...more);

    const { spacing, fontFamily, typography, palette } = theme;
    const baseTheme = { spacing, fontFamily, typography, palette };

    theme = merge({
        actionButton: StyleSheet.create(merge({
            positionContainer: {
                position: 'absolute',
                bottom: 20,
                right: 20,
            },
            container: {
                height: spacing.actionButtonSize,
                width: spacing.actionButtonSize,
                borderRadius: spacing.actionButtonSize / 2,
                backgroundColor: palette.accentColor,
            },
            overlayContainer: {
                ...StyleSheet.absoluteFillObject,
                backgroundColor: Color('#fff').alpha(0.8).toString(),
                // we need overlay to be above the toolbar - so maybe we could use some variable
                // to get elevation for toolbar and this overlay
                ...getPlatformElevation(4),
            },
            toolbarPositionContainer: {
                position: 'absolute',
                bottom: 0,
                right: 0,
                left: 0,
            },
            toolbarContainer: {
                flex: 1,
                height: spacing.actionButtonSize,
                backgroundColor: palette.accentColor,
                flexDirection: 'row',
            },
            toolbarActionContainer: {
                flex: 1,
                alignItems: 'center',
                justifyContent: 'center',
            },
            speedDialContainer: {
                alignItems: 'flex-end',
            },
            speedDialActionContainer: {
                flexDirection: 'row',
                alignItems: 'center',
                paddingLeft: 8,
            },
            speedDialActionIconContainer: {
                width: spacing.actionButtonSize,
                height: spacing.actionButtonSize,
                alignItems: 'center',
                justifyContent: 'center',
            },
            speedDialActionIcon: {
                ...getPlatformElevation(2),
                height: spacing.actionButtonSize - 16,
                width: spacing.actionButtonSize - 16,
                borderRadius: (spacing.actionButtonSize - 16) / 2,
                backgroundColor: grey500,
            },
            speedDialActionLabel: {
                color: palette.secondaryTextColor,
            },
            speedDialActionLabelContainer: {
                ...getPlatformElevation(2),
                borderRadius: 2,
                marginRight: 24,
                paddingVertical: 2,
                paddingHorizontal: 8,
                backgroundColor: grey100,
            },
            icon: {
                color: white,
            },
        }, theme.actionButton)),
        // https://material.google.com/layout/metrics-keylines.html#metrics-keylines-touch-target-size
        avatar: StyleSheet.create(merge({
            container: {
                width: spacing.avatarSize,
                height: spacing.avatarSize,
                borderRadius: spacing.avatarSize / 2,
                backgroundColor: darkenOrLighten(palette.canvasColor, 0.26).toString(),
                alignItems: 'center',
                justifyContent: 'center',
            },
            content: {
                color: palette.canvasColor,
            },
        }, theme.avatar)),
        badge: StyleSheet.create(merge({
            container: {
                position: 'absolute',
                width: 16,
                height: 16,
                borderRadius: 8,
                alignItems: 'center',
                justifyContent: 'center',
                backgroundColor: palette.primaryColor,
            },
            strokeContainer: {
                position: 'absolute',
                width: 16,
                height: 16,
                borderRadius: 8,
                alignItems: 'center',
                justifyContent: 'center',
                backgroundColor: palette.canvasColor,
            },
            content: {
                color: palette.canvasColor,
                fontWeight: fontWeight.medium,
                fontSize: 12,
            },
        }, theme.badge)),
        button: StyleSheet.create(merge({
            container: {
                height: 36,
                alignItems: 'center',
                justifyContent: 'center',
                paddingHorizontal: 16,
                borderRadius: 2,
                flexDirection: 'row',
            },
            text: {
                color: black,
                ...typography.buttons,
            },
            icon: {
                marginRight: 8,
            },
        }, theme.button)),
        buttonFlat: StyleSheet.create(merge({}, theme.buttonFlat)),
        buttonRaised: StyleSheet.create(merge({
            container: {
                backgroundColor: '#fff',
                borderColor: 'rgba(0,0,0,.12)',
            },
        }, theme.buttonRaised)),
        buttonDisabled: StyleSheet.create(merge({
            text: {
                color: palette.disabledTextColor,
            },
        }, theme.buttonDisabled)),
        bottomNavigation: StyleSheet.create(merge({
            container: {
                flexDirection: 'row',
                height: 56,
                backgroundColor: palette.canvasColor,
                borderTopColor: palette.borderColor,
                borderTopWidth: StyleSheet.hairlineWidth,
                ...getPlatformElevation(8),
            },
        }, theme.bottomNavigation)),
        bottomNavigationAction: StyleSheet.create(merge({
            container: {
                flex: 1,
                alignItems: 'center',
                maxWidth: 168,
                minWidth: 80,
                paddingBottom: 12,
                paddingTop: 8,
                paddingLeft: 12,
                paddingRight: 12,
            },
            label: {
                fontSize: 12,
                textAlign: 'center',
                color: palette.secondaryTextColor,
            },
            containerActive: {
                paddingTop: 6,
            },
            iconActive: {
                color: palette.primaryColor,
            },
            labelActive: {
                color: palette.primaryColor,
                fontSize: 14,
            },
        }, theme.bottomNavigationAction)),
        card: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
                borderRadius: 2,
                marginVertical: 4,
                marginHorizontal: 8,
                ...getPlatformElevation(2),
            },
        }, theme.card)),
        dialog: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
                borderRadius: 2,
                ...getPlatformElevation(24),
                width: 280,
                paddingTop: 24,
                paddingHorizontal: 24,
            },
            titleContainer: {
                paddingBottom: 20,
            },
            titleText: {
                fontSize: 20,
                fontWeight: 'bold',
                color: 'black',
            },
            contentContainer: {
                paddingBottom: 24,
            },
            // TODO: merge actionsContainer with actionsInnerContainer
            actionsContainer: {
                height: 56,
                alignItems: 'flex-end',
                justifyContent: 'center',
            },
            actionsInnerContainer: {
                margin: 8,
            },
            defaultActionsContainer: {
                flexDirection: 'row',
            },
        }, theme.dialog)),
        checkbox: StyleSheet.create(merge({
            container: {
                flex: 1,
                flexDirection: 'row',
                alignItems: 'center',
            },
            icon: {
                color: palette.primaryColor,
            },
            label: {
                color: black,
                marginLeft: 20,
                flex: 1,
            },
        }, theme.checkbox)),
        divider: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.borderColor,
                height: StyleSheet.hairlineWidth,
            },
        }, theme.divider)),
        drawer: StyleSheet.create(merge({
            container: {
                flex: 1,
                backgroundColor: white,
            },
        }, theme.drawer)),
        drawerHeader: StyleSheet.create(merge({
            container: {
                position: 'absolute',
                top: 0,
                left: 0,
                right: 0,
            },
            contentContainer: {
                backgroundColor: grey500,
                height: 150,
            },
        }, theme.drawerHeader)),
        drawerHeaderAccount: StyleSheet.create(merge({
            container: {
                flex: 1,
                paddingBottom: 8,
            },
            accountContainer: {
                flex: 1,
                paddingHorizontal: 16,
                marginBottom: 8,
            },
            topContainer: {
                flex: 1,
                justifyContent: 'center',
            },
            avatarsContainer: {
                flexDirection: 'row',
            },
            activeAvatarContainer: {
                flex: 1,
            },
            inactiveAvatarContainer: {
                paddingLeft: 8,
            },
        }, theme.drawerHeaderAccount)),
        drawerHeaderListItem: StyleSheet.create(merge({
            container: {
                backgroundColor: transparent,
            },
        }, theme.drawerHeaderListItem)),
        drawerSection: StyleSheet.create(merge({
            container: {
                paddingVertical: 8,
            },
            item: {
                flex: 1,
                flexDirection: 'row',
                alignItems: 'center',
                height: 48,
                paddingLeft: 16,
            },
            subheader: {
                flex: 1,
            },
            icon: {
                position: 'absolute',
                top: 13,
            },
            value: {
                flex: 1,
                paddingLeft: 56,
                top: 2,
            },
            label: {
                paddingRight: 16,
                top: 2,
            },
        }, theme.drawerSection)),
        drawerSectionActiveItem: StyleSheet.create(merge({
            container: {
                backgroundColor: grey100,
            },
            leftElement: {
                color: palette.primaryColor,
            },
            primaryText: {
                ...typography.buttons,
                color: palette.primaryColor,
            },
        }, theme.drawerSectionActiveItem)),
        iconToggle: StyleSheet.create(merge({
            container: {
                width: spacing.iconSize * 2,
                height: spacing.iconSize * 2,
                alignItems: 'center',
                justifyContent: 'center',
            },
            icon: {
                color: palette.secondaryTextColor,
            },
        }, theme.iconToggle)),
        listItem: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
                height: 56,
            },
            contentViewContainer: {
                flex: 1,
                flexDirection: 'row',
                alignItems: 'center',
            },
            leftElementContainer: {
                width: 40,
                marginLeft: 16,
            },
            centerElementContainer: {
                paddingLeft: 16,
                flex: 1,
            },
            textViewContainer: { },
            primaryText: {
                lineHeight: 24,
                color: palette.primaryTextColor,
                ...typography.subheading,
            },
            firstLine: {
                flexDirection: 'row',
            },
            primaryTextContainer: {
                flex: 1,
            },
            secondaryText: {
                lineHeight: 22,
                color: palette.secondaryTextColor,
                ...typography.body1,
            },
            tertiaryText: {
                lineHeight: 22,
                color: palette.secondaryTextColor,
                ...typography.body1,
            },
            rightElementContainer: {
                paddingRight: 4,
            },
            leftElement: {
                margin: 16,
                color: palette.secondaryTextColor,
            },
            rightElement: {
                color: palette.secondaryTextColor,
            },
        }, theme.listItem)),
        // https://material.google.com/components/subheaders.html#
        subheader: StyleSheet.create(merge({
            container: {
                height: 48,
                justifyContent: 'center',
            },
            text: {
                color: palette.secondaryTextColor,
                // https://material.google.com/components/subheaders.html#subheaders-grid-subheaders
                ...typography.body2,
            },
        }, theme.subheader)),
        toolbar: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.primaryColor,
                height: 56,
                flexDirection: 'row',
                alignItems: 'center',
                paddingHorizontal: 4,
                overflow: 'hidden',
                ...getPlatformElevation(4),
            },
            leftElementContainer: { },
            leftElement: {
                color: palette.alternateTextColor,
            },
            centerElementContainer: {
                flex: 1,
                marginLeft: 20,
            },
            titleText: {
                color: palette.alternateTextColor,
                ...typography.appBar,
            },
            rightElementContainer: {
                flexDirection: 'row',
            },
            rightElement: {
                color: palette.alternateTextColor,
            },
        }, theme.toolbar)),
        toolbarSearchActive: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
            },
            leftElement: {
                color: palette.secondaryTextColor,
            },
            centerElementContainer: { },
            titleText: {
                flex: 1,
                marginLeft: 16,
                color: palette.primaryTextColor,
                fontWeight: fontWeight.normal,
            },
            rightElement: {
                color: palette.secondaryTextColor,
            },
        }, theme.toolbarSearchActive)),
    }, baseTheme);

    return theme;
}
<commit_msg>Add user supplied fontFamily to Toolbar and Dialog title (#100)<commit_after>/* eslint-disable import/no-unresolved, import/extensions */
import { StyleSheet } from 'react-native';
/* eslint-enable import/no-unresolved, import/extensions */

import Color from 'color';
import merge from 'lodash.merge';

import { fontWeight } from './typography';
import {
  black, grey100, grey500, white, transparent,
} from './colors';

import lightTheme from './themes/light';
import getPlatformElevation from './getPlatformElevation';

function darkenOrLighten(color, ratio = 0.15) {
    const c = Color(color);
    return c.luminosity() > 0.5 ? c.darken(ratio) : c.lighten(ratio);
}

export default function getTheme(theme, ...more) {
    theme = merge(lightTheme, theme, ...more);

    const { spacing, fontFamily, typography, palette } = theme;
    const baseTheme = { spacing, fontFamily, typography, palette };

    theme = merge({
        actionButton: StyleSheet.create(merge({
            positionContainer: {
                position: 'absolute',
                bottom: 20,
                right: 20,
            },
            container: {
                height: spacing.actionButtonSize,
                width: spacing.actionButtonSize,
                borderRadius: spacing.actionButtonSize / 2,
                backgroundColor: palette.accentColor,
            },
            overlayContainer: {
                ...StyleSheet.absoluteFillObject,
                backgroundColor: Color('#fff').alpha(0.8).toString(),
                // we need overlay to be above the toolbar - so maybe we could use some variable
                // to get elevation for toolbar and this overlay
                ...getPlatformElevation(4),
            },
            toolbarPositionContainer: {
                position: 'absolute',
                bottom: 0,
                right: 0,
                left: 0,
            },
            toolbarContainer: {
                flex: 1,
                height: spacing.actionButtonSize,
                backgroundColor: palette.accentColor,
                flexDirection: 'row',
            },
            toolbarActionContainer: {
                flex: 1,
                alignItems: 'center',
                justifyContent: 'center',
            },
            speedDialContainer: {
                alignItems: 'flex-end',
            },
            speedDialActionContainer: {
                flexDirection: 'row',
                alignItems: 'center',
                paddingLeft: 8,
            },
            speedDialActionIconContainer: {
                width: spacing.actionButtonSize,
                height: spacing.actionButtonSize,
                alignItems: 'center',
                justifyContent: 'center',
            },
            speedDialActionIcon: {
                ...getPlatformElevation(2),
                height: spacing.actionButtonSize - 16,
                width: spacing.actionButtonSize - 16,
                borderRadius: (spacing.actionButtonSize - 16) / 2,
                backgroundColor: grey500,
            },
            speedDialActionLabel: {
                color: palette.secondaryTextColor,
            },
            speedDialActionLabelContainer: {
                ...getPlatformElevation(2),
                borderRadius: 2,
                marginRight: 24,
                paddingVertical: 2,
                paddingHorizontal: 8,
                backgroundColor: grey100,
            },
            icon: {
                color: white,
            },
        }, theme.actionButton)),
        // https://material.google.com/layout/metrics-keylines.html#metrics-keylines-touch-target-size
        avatar: StyleSheet.create(merge({
            container: {
                width: spacing.avatarSize,
                height: spacing.avatarSize,
                borderRadius: spacing.avatarSize / 2,
                backgroundColor: darkenOrLighten(palette.canvasColor, 0.26).toString(),
                alignItems: 'center',
                justifyContent: 'center',
            },
            content: {
                color: palette.canvasColor,
            },
        }, theme.avatar)),
        badge: StyleSheet.create(merge({
            container: {
                position: 'absolute',
                width: 16,
                height: 16,
                borderRadius: 8,
                alignItems: 'center',
                justifyContent: 'center',
                backgroundColor: palette.primaryColor,
            },
            strokeContainer: {
                position: 'absolute',
                width: 16,
                height: 16,
                borderRadius: 8,
                alignItems: 'center',
                justifyContent: 'center',
                backgroundColor: palette.canvasColor,
            },
            content: {
                color: palette.canvasColor,
                fontWeight: fontWeight.medium,
                fontSize: 12,
            },
        }, theme.badge)),
        button: StyleSheet.create(merge({
            container: {
                height: 36,
                alignItems: 'center',
                justifyContent: 'center',
                paddingHorizontal: 16,
                borderRadius: 2,
                flexDirection: 'row',
            },
            text: {
                color: black,
                ...typography.buttons,
            },
            icon: {
                marginRight: 8,
            },
        }, theme.button)),
        buttonFlat: StyleSheet.create(merge({}, theme.buttonFlat)),
        buttonRaised: StyleSheet.create(merge({
            container: {
                backgroundColor: '#fff',
                borderColor: 'rgba(0,0,0,.12)',
            },
        }, theme.buttonRaised)),
        buttonDisabled: StyleSheet.create(merge({
            text: {
                color: palette.disabledTextColor,
            },
        }, theme.buttonDisabled)),
        bottomNavigation: StyleSheet.create(merge({
            container: {
                flexDirection: 'row',
                height: 56,
                backgroundColor: palette.canvasColor,
                borderTopColor: palette.borderColor,
                borderTopWidth: StyleSheet.hairlineWidth,
                ...getPlatformElevation(8),
            },
        }, theme.bottomNavigation)),
        bottomNavigationAction: StyleSheet.create(merge({
            container: {
                flex: 1,
                alignItems: 'center',
                maxWidth: 168,
                minWidth: 80,
                paddingBottom: 12,
                paddingTop: 8,
                paddingLeft: 12,
                paddingRight: 12,
            },
            label: {
                fontSize: 12,
                textAlign: 'center',
                color: palette.secondaryTextColor,
            },
            containerActive: {
                paddingTop: 6,
            },
            iconActive: {
                color: palette.primaryColor,
            },
            labelActive: {
                color: palette.primaryColor,
                fontSize: 14,
            },
        }, theme.bottomNavigationAction)),
        card: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
                borderRadius: 2,
                marginVertical: 4,
                marginHorizontal: 8,
                ...getPlatformElevation(2),
            },
        }, theme.card)),
        dialog: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
                borderRadius: 2,
                ...getPlatformElevation(24),
                width: 280,
                paddingTop: 24,
                paddingHorizontal: 24,
            },
            titleContainer: {
                paddingBottom: 20,
            },
            titleText: {
                fontFamily,
                fontSize: 20,
                fontWeight: 'bold',
                color: 'black',
            },
            contentContainer: {
                paddingBottom: 24,
            },
            // TODO: merge actionsContainer with actionsInnerContainer
            actionsContainer: {
                height: 56,
                alignItems: 'flex-end',
                justifyContent: 'center',
            },
            actionsInnerContainer: {
                margin: 8,
            },
            defaultActionsContainer: {
                flexDirection: 'row',
            },
        }, theme.dialog)),
        checkbox: StyleSheet.create(merge({
            container: {
                flex: 1,
                flexDirection: 'row',
                alignItems: 'center',
            },
            icon: {
                color: palette.primaryColor,
            },
            label: {
                color: black,
                marginLeft: 20,
                flex: 1,
            },
        }, theme.checkbox)),
        divider: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.borderColor,
                height: StyleSheet.hairlineWidth,
            },
        }, theme.divider)),
        drawer: StyleSheet.create(merge({
            container: {
                flex: 1,
                backgroundColor: white,
            },
        }, theme.drawer)),
        drawerHeader: StyleSheet.create(merge({
            container: {
                position: 'absolute',
                top: 0,
                left: 0,
                right: 0,
            },
            contentContainer: {
                backgroundColor: grey500,
                height: 150,
            },
        }, theme.drawerHeader)),
        drawerHeaderAccount: StyleSheet.create(merge({
            container: {
                flex: 1,
                paddingBottom: 8,
            },
            accountContainer: {
                flex: 1,
                paddingHorizontal: 16,
                marginBottom: 8,
            },
            topContainer: {
                flex: 1,
                justifyContent: 'center',
            },
            avatarsContainer: {
                flexDirection: 'row',
            },
            activeAvatarContainer: {
                flex: 1,
            },
            inactiveAvatarContainer: {
                paddingLeft: 8,
            },
        }, theme.drawerHeaderAccount)),
        drawerHeaderListItem: StyleSheet.create(merge({
            container: {
                backgroundColor: transparent,
            },
        }, theme.drawerHeaderListItem)),
        drawerSection: StyleSheet.create(merge({
            container: {
                paddingVertical: 8,
            },
            item: {
                flex: 1,
                flexDirection: 'row',
                alignItems: 'center',
                height: 48,
                paddingLeft: 16,
            },
            subheader: {
                flex: 1,
            },
            icon: {
                position: 'absolute',
                top: 13,
            },
            value: {
                flex: 1,
                paddingLeft: 56,
                top: 2,
            },
            label: {
                paddingRight: 16,
                top: 2,
            },
        }, theme.drawerSection)),
        drawerSectionActiveItem: StyleSheet.create(merge({
            container: {
                backgroundColor: grey100,
            },
            leftElement: {
                color: palette.primaryColor,
            },
            primaryText: {
                ...typography.buttons,
                color: palette.primaryColor,
            },
        }, theme.drawerSectionActiveItem)),
        iconToggle: StyleSheet.create(merge({
            container: {
                width: spacing.iconSize * 2,
                height: spacing.iconSize * 2,
                alignItems: 'center',
                justifyContent: 'center',
            },
            icon: {
                color: palette.secondaryTextColor,
            },
        }, theme.iconToggle)),
        listItem: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
                height: 56,
            },
            contentViewContainer: {
                flex: 1,
                flexDirection: 'row',
                alignItems: 'center',
            },
            leftElementContainer: {
                width: 40,
                marginLeft: 16,
            },
            centerElementContainer: {
                paddingLeft: 16,
                flex: 1,
            },
            textViewContainer: { },
            primaryText: {
                lineHeight: 24,
                color: palette.primaryTextColor,
                ...typography.subheading,
            },
            firstLine: {
                flexDirection: 'row',
            },
            primaryTextContainer: {
                flex: 1,
            },
            secondaryText: {
                lineHeight: 22,
                color: palette.secondaryTextColor,
                ...typography.body1,
            },
            tertiaryText: {
                lineHeight: 22,
                color: palette.secondaryTextColor,
                ...typography.body1,
            },
            rightElementContainer: {
                paddingRight: 4,
            },
            leftElement: {
                margin: 16,
                color: palette.secondaryTextColor,
            },
            rightElement: {
                color: palette.secondaryTextColor,
            },
        }, theme.listItem)),
        // https://material.google.com/components/subheaders.html#
        subheader: StyleSheet.create(merge({
            container: {
                height: 48,
                justifyContent: 'center',
            },
            text: {
                color: palette.secondaryTextColor,
                // https://material.google.com/components/subheaders.html#subheaders-grid-subheaders
                ...typography.body2,
            },
        }, theme.subheader)),
        toolbar: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.primaryColor,
                height: 56,
                flexDirection: 'row',
                alignItems: 'center',
                paddingHorizontal: 4,
                overflow: 'hidden',
                ...getPlatformElevation(4),
            },
            leftElementContainer: { },
            leftElement: {
                color: palette.alternateTextColor,
            },
            centerElementContainer: {
                flex: 1,
                marginLeft: 20,
            },
            titleText: {
                fontFamily,
                color: palette.alternateTextColor,
                ...typography.appBar,
            },
            rightElementContainer: {
                flexDirection: 'row',
            },
            rightElement: {
                color: palette.alternateTextColor,
            },
        }, theme.toolbar)),
        toolbarSearchActive: StyleSheet.create(merge({
            container: {
                backgroundColor: palette.canvasColor,
            },
            leftElement: {
                color: palette.secondaryTextColor,
            },
            centerElementContainer: { },
            titleText: {
                fontFamily,
                flex: 1,
                marginLeft: 16,
                color: palette.primaryTextColor,
                fontWeight: fontWeight.normal,
            },
            rightElement: {
                color: palette.secondaryTextColor,
            },
        }, theme.toolbarSearchActive)),
    }, baseTheme);

    return theme;
}
<|endoftext|>


<commit_before><commit_msg>IE testing new interval<commit_after><|endoftext|>


<commit_before>var playerController = function($scope, $http, config, playerFactory) {
	var self = this;
	self.players = [];
	self.player = {};
	self.serverError = false;

	// Call factory's method here
	self.players = playerFactory.getPlayers().then(function(players) {
		console.log(players);
		self.players = players;
		self.serverError = false;
	}, function(error) {
		self.serverError = error;
	});

	$scope.getPlayer = function(player) {
		$event.preventDefault();
		self.player = player;
	};

	$scope.updatPlayer = function(player) {
		$event.preventDefault();
	};

	// TODO UPDATE METHOD

};
playerController.$inject = ['$scope', '$http', 'config', 'playerFactory'];
ihr.controller('playerController', playerController);<commit_msg>fix controller<commit_after>var playerController = function($scope, $http, config, playerFactory) {
	var self = this;
	self.players = [];
	self.player = {};
	self.serverError = false;

	// Call factory's method here
	self.players = playerFactory.getPlayers().then(function(players) {
		console.log(players);
		self.players = players;
		self.serverError = false;
	}, function(error) {
		self.serverError = error;
	});

	$scope.getPlayer = function(player) {
		self.player = player;
	};

	$scope.updatPlayer = function(player) {
		playerFactory.updatePlayer(self.player).then(function(player) {
			self.serverError = false;
		}, function(error) {
			self.serverError = error;
		});
	};

	// TODO UPDATE METHOD

};
playerController.$inject = ['$scope', '$http', 'config', 'playerFactory'];
ihr.controller('playerController', playerController);<|endoftext|>


<commit_before>(function () {
  var h = require('virtual-dom/h');
  var _ = {
    isString: require('lodash.isstring')
  };

  function constructor(property, configService, configValue, disabled) {
    if (_.isString(configValue)) {
      configValue = configValue == 'true';
    }
    return h('div.form-item', [
      h('div.form-item__label', h('label', {
        title     : property.description,
        'ev-click': function (e) {
          if(!disabled) {
            var _checkbox = e.target.parentNode.parentNode.querySelector('input');
            var _val = _checkbox.checked;
            _checkbox.checked = !_val;
            if (property.defaults !== !_val) {
              configService.setValue(property.fullname, !_val);
            } else {
              configService.removeValue(property.fullname);
            }
          }
        }
      }, [property.title])),
      h('div.form-item__input', h('input', {
        disabled  : disabled,
        'type'    : 'checkbox',
        'checked' : configValue,
        'ev-click': function (e) {
          if (property.defaults !== e.target.checked) {
            configService.setValue(property.fullname, e.target.checked);
          } else {
            configService.removeValue(property.fullname);
          }
        }
      }))
    ]);
  }

  module.exports = constructor;
})();
<commit_msg>checkbox state on init<commit_after>(function () {
  var h = require('virtual-dom/h');
  var _ = {
    isString: require('lodash.isstring'),
    isUndefined: require('lodash.isundefined')
  };

  function constructor(property, configService, configValue, disabled) {

    if (_.isString(configValue)) {
      configValue = configValue == 'true';
    }
    property.defaults = property.defaults === 'true';

    return h('div.form-item', [
      h('div.form-item__label', h('label', {
        title     : property.description,
        'ev-click': function (e) {
          if(!disabled) {
            var _checkbox = e.target.parentNode.parentNode.querySelector('input');
            var _val = _checkbox.checked;
            _checkbox.checked = !_val;
            if (property.defaults !== !_val) {
              configService.setValue(property.fullname, !_val);
            } else {
              configService.removeValue(property.fullname);
            }
          }
        }
      }, [property.title])),
      h('div.form-item__input', h('input', {
        disabled  : disabled,
        'type'    : 'checkbox',
        'checked': _.isUndefined(configValue) ? property.defaults : !property.defaults,
        'ev-click': function (e) {
          if (property.defaults !== e.target.checked) {
            configService.setValue(property.fullname, e.target.checked);
          } else {
            configService.removeValue(property.fullname);
          }
        }
      }))
    ]);
  }

  module.exports = constructor;
})();
<|endoftext|>