<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

var App = require('app');
require('utils/configs/defaults_providers/defaultsProvider');

App.YARNDefaultsProvider = App.DefaultsProvider.create({

  /**
   * List of the configs that should be calculated
   */
  configsTemplate: {
    'yarn.nodemanager.resource.memory-mb': null,
    'yarn.scheduler.minimum-allocation-mb': null,
    'yarn.scheduler.maximum-allocation-mb': null,
    'mapreduce.map.memory.mb': null,
    'mapreduce.reduce.memory.mb': null,
    'mapreduce.map.java.opts': null,
    'mapreduce.reduce.java.opts': null,
    'mapreduce.task.io.sort.mb': null,
    'yarn.app.mapreduce.am.resource.mb': null,
    'yarn.app.mapreduce.am.command-opts': null
  },

  /**
   * Information about ram, disk count, cpu count and hbase availability
   * Example:
   * {
   *   disk: 12,
   *   ram: 48 * 1024, // MB
   *   cpu: 12,
   *   hBaseInstalled: false
   * }
   */
  clusterData: null,

  /**
   * Reserved for system memory
   *
   * Value in MB!
   */
  reservedRam: null,

  /**
   * Reserved for HBase memory
   *
   * Value in MB!
   */
  hBaseRam: null,

  GB: 1024,
  /**
   *  Minimum container size (in RAM).
   *  This value is dependent on the amount of RAM available, as in smaller memory nodes the minimum container size should also be smaller
   *
   *  Value in MB!
   */
  recommendedMinimumContainerSize: function () {
    if (!this.clusterDataIsValid()) return null;
    var ram = this.get('clusterData.ram');
    switch (true) {
      case (ram <=4 ):
        return 256;
      case (ram <= 8):
        return 512;
      case (ram <= 24):
        return 1024;
      default:
        return 2048;
    }
  }.property('clusterData.ram'),

  /**
   * Maximum number of containers allowed per node
   * max (2*cores,min (1.8*DISKS,(Total available RAM) / MIN_CONTAINER_SIZE)))
   * min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE)
   */
  containers: function () {
    if (!this.clusterDataIsValid()) return null;
    var cpu = this.get('clusterData.cpu');
    var disk = this.get('clusterData.disk');
    var ram = this.get('clusterData.ram');
    var containerSize = this.get('recommendedMinimumContainerSize');
    cpu *= 2;
    disk = Math.ceil(disk * 1.8);
    ram = (ram - this.get('reservedRam'));
    if (this.get('clusterData.hBaseInstalled')) {
      ram -= this.get('hBaseRam')
    }
    if (ram < 1) {
      ram = 1;
    }
    ram *= this.get('GB');
    ram /= containerSize;
    return Math.round(Math.min(cpu, Math.min(disk, ram)));
  }.property('clusterData.cpu', 'clusterData.ram', 'clusterData.hBaseInstalled', 'clusterData.disk', 'reservedRam', 'hBaseRam', 'recommendedMinimumContainerSize'),

  /**
   * amount of RAM per container
   * RAM-per-container = abs(MIN_CONTAINER_SIZE, (Total Available RAM) / containers))
   *
   * Value in MB!
   */
  ramPerContainer: function () {
    var containers = this.get('containers');
    var ram = this.get('clusterData.ram');
    ram = (ram - this.get('reservedRam'));
    if (this.get('clusterData.hBaseInstalled')) {
      ram -= this.get('hBaseRam')
    }
    if (ram < 1) {
      ram = 1;
    }
    ram *= this.get('GB');
    var container_ram = Math.abs(ram / containers);
    return container_ram > this.get('GB') ? container_ram / (512 * 512) : container_ram;
  }.property('recommendedMinimumContainerSize', 'containers', 'clusterData.ram', 'clusterData.hBaseInstalled', 'hBaseRam', 'reservedRam'),

  mapMemory: function () {
    return this.get('ramPerContainer');
  }.property('ramPerContainer'),

  reduceMemory: function () {
    var ramPerContainer = this.get('ramPerContainer');
    return ramPerContainer <= 2048 ? 2 * ramPerContainer : ramPerContainer;
  }.property('ramPerContainer'),

  amMemory: function () {
    return Math.max(this.get('mapMemory'), this.get('reduceMemory'));
  }.property('mapMemory', 'reduceMemory'),

  /**
   * Reserved for HBase and system memory is based on total available memory
   */

  reservedStackRecommendations: function () {
    var memory = this.get('clusterData.ram');
    var reservedStack = { 4: 1, 8: 2, 16: 2, 24: 4, 48: 6, 64: 8, 72: 8, 96: 12,
      128: 24, 256: 32, 512: 64};

    if (memory in reservedStack) {
      this.set('reservedRam', reservedStack[memory]);
    }
    if (memory <= 4)
      this.set('reservedRam', 1);
    else if (memory >= 512)
      this.set('reservedRam', 64);
    else
      this.set('reservedRam', 1);
  }.observes('clusterData.ram'),

  hbaseMemRecommendations: function () {
    var memory = this.get('clusterData.ram');
    var reservedHBase = {4:1, 8:1, 16:2, 24:4, 48:8, 64:8, 72:8, 96:16,
      128:24, 256:32, 512:64};

    if (memory in reservedHBase) {
      this.set('reservedRam', reservedHBase[memory]);
    }
    if (memory <= 4)
      this.set('hBaseRam', 1);
    else if (memory >= 512)
      this.set('hBaseRam', 64);
    else
      this.set('hBaseRam', 2);

  }.observes('clusterData.ram'),

  /**
   * Provide an object where keys are property-names and values are the recommended defaults
   * @param {object} localDB Object with information about hosts and master/slave components
   * Example:
   *
   *    {
   *       "hosts": {
   *           "host1": {
   *               "name": "host1",
   *               "cpu": 1,
   *               "memory": "6123683.00",
   *               "disk_info": [{
   *                   ....
   *               },...]
   *           },...
   *       },
   *       "masterComponentHosts": [{
   *           "component": "NAMENODE",
   *           "hostName": "host1",
   *           "serviceId": "HDFS"
   *       },...],
   *       "slaveComponentHosts": [{
   *           "componentName": "DATANODE",
   *           "hosts": [{
   *               "hostName": "host2"
   *           }]
   *       },...]
   *   }
   *
   * @return {object}
   */
  getDefaults: function (localDB) {
    this._super();
    this.getClusterData(localDB);
    var configs = {};
    jQuery.extend(configs, this.get('configsTemplate'));
    configs['yarn.nodemanager.resource.memory-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
    configs['yarn.scheduler.minimum-allocation-mb'] = Math.round(this.get('ramPerContainer'));
    configs['yarn.scheduler.maximum-allocation-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
    configs['yarn.app.mapreduce.am.resource.mb'] = Math.round(this.get('amMemory'));
    configs['yarn.app.mapreduce.am.command-opts'] = "-Xmx" + Math.round(0.8 * this.get('amMemory')) + "m";
    configs['mapreduce.map.memory.mb'] = Math.round(this.get('mapMemory'));
    configs['mapreduce.reduce.memory.mb'] = Math.round(this.get('reduceMemory'));
    configs['mapreduce.map.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('mapMemory')) + "m";
    configs['mapreduce.reduce.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('reduceMemory')) + "m";
    configs['mapreduce.task.io.sort.mb'] = Math.round(0.4 * this.get('mapMemory'));
    return configs;
  },

  /**
   * Calculate needed cluster data (like disk count, cpu count, ram (in MB!) and hbase availability)
   * @param {object} localDB Object with information about hosts and master/slave components
   */
  getClusterData: function (localDB) {
    this._super();
    var components = ['NODEMANAGER'];
    var hosts = [];
    if (!localDB.hosts || !(localDB.masterComponentHosts || localDB.slaveComponentHosts)) return;
    var hBaseInstalled = !!localDB.masterComponentHosts.filterProperty('component', 'HBASE_MASTER').length;
    components.forEach(function (component) {
      var mc = localDB.masterComponentHosts.findProperty('component', component);
      if (mc) {
        if (!hosts.contains(mc.hostName)) {
          hosts.push(mc.hostName);
        }
      }
      else {
        var sc = localDB.slaveComponentHosts.findProperty('componentName', component);
        if (sc) {
          sc.hosts.map(function (host) {
            if (!hosts.contains(host.hostName)) {
              hosts.push(host.hostName);
            }
          });
        }
      }
    });
    var clusterData = {
      cpu: 0,
      disk: 0,
      ram: 0,
      hBaseInstalled: hBaseInstalled
    };
    var host = hosts[0] && localDB.hosts[hosts[0]];
    if (host) {
      clusterData.cpu = parseInt(host.cpu);
      var length = 0;
      host.disk_info.forEach(function(disk) {
        //invalid mountpoints
        if (!(disk.mountpoint.startsWith('/home/') || disk.mountpoint.startsWith('/homes/') ||
        		disk.mountpoint.startsWith('/dev/') || disk.mountpoint.startsWith('/tmp/'))) {
          length++;
        }
      },this);
      clusterData.disk = length;
      clusterData.ram = Math.round(parseFloat(host.memory) / (1024 * 1024));
    }
    this.set('clusterData', clusterData);
  },

  /**
   * Verify clusterData - check if all properties are defined
   */
  clusterDataIsValid: function () {
    if (!this.get('clusterData')) return false;
    if (this.get('clusterData.ram') == null || this.get('clusterData.cpu') == null || this.get('clusterData.disk') == null || this.get('clusterData.hBaseInstalled') == null) return false;
    return true;
  }

});
<commit_msg>AMBARI-3743. YARN dynamic configs generate 0 values nodes. (srimanth)<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

var App = require('app');
require('utils/configs/defaults_providers/defaultsProvider');

App.YARNDefaultsProvider = App.DefaultsProvider.create({

  /**
   * List of the configs that should be calculated
   */
  configsTemplate: {
    'yarn.nodemanager.resource.memory-mb': null,
    'yarn.scheduler.minimum-allocation-mb': null,
    'yarn.scheduler.maximum-allocation-mb': null,
    'mapreduce.map.memory.mb': null,
    'mapreduce.reduce.memory.mb': null,
    'mapreduce.map.java.opts': null,
    'mapreduce.reduce.java.opts': null,
    'mapreduce.task.io.sort.mb': null,
    'yarn.app.mapreduce.am.resource.mb': null,
    'yarn.app.mapreduce.am.command-opts': null
  },

  /**
   * Information about ram, disk count, cpu count and hbase availability
   * Example:
   * {
   *   disk: 12,
   *   ram: 48 * 1024, // MB
   *   cpu: 12,
   *   hBaseInstalled: false
   * }
   */
  clusterData: null,

  /**
   * Reserved for system memory
   *
   * Value in MB!
   */
  reservedRam: null,

  /**
   * Reserved for HBase memory
   *
   * Value in MB!
   */
  hBaseRam: null,

  GB: 1024,
  /**
   *  Minimum container size (in RAM).
   *  This value is dependent on the amount of RAM available, as in smaller memory nodes the minimum container size should also be smaller
   *
   *  Value in MB!
   */
  recommendedMinimumContainerSize: function () {
    if (!this.clusterDataIsValid()) return null;
    var ram = this.get('clusterData.ram');
    switch (true) {
      case (ram <=4 ):
        return 256;
      case (ram <= 8):
        return 512;
      case (ram <= 24):
        return 1024;
      default:
        return 2048;
    }
  }.property('clusterData.ram'),

  /**
   * Maximum number of containers allowed per node
   * max (2*cores,min (1.8*DISKS,(Total available RAM) / MIN_CONTAINER_SIZE)))
   * min (2*CORES, 1.8*DISKS, (Total available RAM) / MIN_CONTAINER_SIZE)
   */
  containers: function () {
    if (!this.clusterDataIsValid()) return null;
    var cpu = this.get('clusterData.cpu');
    var disk = this.get('clusterData.disk');
    var ram = this.get('clusterData.ram');
    var containerSize = this.get('recommendedMinimumContainerSize');
    cpu *= 2;
    disk = Math.ceil(disk * 1.8);
    ram = (ram - this.get('reservedRam'));
    if (this.get('clusterData.hBaseInstalled')) {
      ram -= this.get('hBaseRam')
    }
    if (ram < 1) {
      ram = 1;
    }
    ram *= this.get('GB');
    ram /= containerSize;
    return Math.round(Math.min(cpu, Math.min(disk, ram)));
  }.property('clusterData.cpu', 'clusterData.ram', 'clusterData.hBaseInstalled', 'clusterData.disk', 'reservedRam', 'hBaseRam', 'recommendedMinimumContainerSize'),

  /**
   * Amount of RAM per container.
   * Calculated to be max(1GB, RAM - reservedRam - hBaseRam) / containers
   *
   * @return Memory per container in MB. If greater than 1GB,
   *          value will be in multiples of 512.
   */
  ramPerContainer: function () {
    var containers = this.get('containers');
    var ram = this.get('clusterData.ram');
    ram = (ram - this.get('reservedRam'));
    if (this.get('clusterData.hBaseInstalled')) {
      ram -= this.get('hBaseRam')
    }
    // On low memory systems, memory left over after
    // removing reserved-RAM and HBase might be
    // less than 1GB (even negative). If so, we force
    // a 1GB value relying on virtual memory.
    if (ram < 1) {
      ram = 1;
    }
    ram *= this.get('GB');
    var container_ram = Math.abs(ram / containers);
    // If container memory is greater than 1GB,
    // we use multiples of 512 as value
    return container_ram > this.get('GB') ? (Math.floor(container_ram / 512) * 512) : container_ram;
  }.property('recommendedMinimumContainerSize', 'containers', 'clusterData.ram', 'clusterData.hBaseInstalled', 'hBaseRam', 'reservedRam'),

  mapMemory: function () {
    return this.get('ramPerContainer');
  }.property('ramPerContainer'),

  reduceMemory: function () {
    var ramPerContainer = this.get('ramPerContainer');
    return ramPerContainer <= 2048 ? 2 * ramPerContainer : ramPerContainer;
  }.property('ramPerContainer'),

  amMemory: function () {
    return Math.max(this.get('mapMemory'), this.get('reduceMemory'));
  }.property('mapMemory', 'reduceMemory'),

  /**
   * Reserved for HBase and system memory is based on total available memory
   */

  reservedStackRecommendations: function () {
    var memory = this.get('clusterData.ram');
    var reservedStack = { 4: 1, 8: 2, 16: 2, 24: 4, 48: 6, 64: 8, 72: 8, 96: 12,
      128: 24, 256: 32, 512: 64};

    if (memory in reservedStack) {
      this.set('reservedRam', reservedStack[memory]);
    }
    if (memory <= 4)
      this.set('reservedRam', 1);
    else if (memory >= 512)
      this.set('reservedRam', 64);
    else
      this.set('reservedRam', 1);
  }.observes('clusterData.ram'),

  hbaseMemRecommendations: function () {
    var memory = this.get('clusterData.ram');
    var reservedHBase = {4:1, 8:1, 16:2, 24:4, 48:8, 64:8, 72:8, 96:16,
      128:24, 256:32, 512:64};

    if (memory in reservedHBase) {
      this.set('reservedRam', reservedHBase[memory]);
    }
    if (memory <= 4)
      this.set('hBaseRam', 1);
    else if (memory >= 512)
      this.set('hBaseRam', 64);
    else
      this.set('hBaseRam', 2);

  }.observes('clusterData.ram'),

  /**
   * Provide an object where keys are property-names and values are the recommended defaults
   * @param {object} localDB Object with information about hosts and master/slave components
   * Example:
   *
   *    {
   *       "hosts": {
   *           "host1": {
   *               "name": "host1",
   *               "cpu": 1,
   *               "memory": "6123683.00",
   *               "disk_info": [{
   *                   ....
   *               },...]
   *           },...
   *       },
   *       "masterComponentHosts": [{
   *           "component": "NAMENODE",
   *           "hostName": "host1",
   *           "serviceId": "HDFS"
   *       },...],
   *       "slaveComponentHosts": [{
   *           "componentName": "DATANODE",
   *           "hosts": [{
   *               "hostName": "host2"
   *           }]
   *       },...]
   *   }
   *
   * @return {object}
   */
  getDefaults: function (localDB) {
    this._super();
    this.getClusterData(localDB);
    var configs = {};
    jQuery.extend(configs, this.get('configsTemplate'));
    configs['yarn.nodemanager.resource.memory-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
    configs['yarn.scheduler.minimum-allocation-mb'] = Math.round(this.get('ramPerContainer'));
    configs['yarn.scheduler.maximum-allocation-mb'] = Math.round(this.get('containers') * this.get('ramPerContainer'));
    configs['yarn.app.mapreduce.am.resource.mb'] = Math.round(this.get('amMemory'));
    configs['yarn.app.mapreduce.am.command-opts'] = "-Xmx" + Math.round(0.8 * this.get('amMemory')) + "m";
    configs['mapreduce.map.memory.mb'] = Math.round(this.get('mapMemory'));
    configs['mapreduce.reduce.memory.mb'] = Math.round(this.get('reduceMemory'));
    configs['mapreduce.map.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('mapMemory')) + "m";
    configs['mapreduce.reduce.java.opts'] = "-Xmx" + Math.round(0.8 * this.get('reduceMemory')) + "m";
    configs['mapreduce.task.io.sort.mb'] = Math.round(0.4 * this.get('mapMemory'));
    return configs;
  },

  /**
   * Calculate needed cluster data (like disk count, cpu count, ram (in MB!) and hbase availability)
   * @param {object} localDB Object with information about hosts and master/slave components
   */
  getClusterData: function (localDB) {
    this._super();
    var components = ['NODEMANAGER'];
    var hosts = [];
    if (!localDB.hosts || !(localDB.masterComponentHosts || localDB.slaveComponentHosts)) return;
    var hBaseInstalled = !!localDB.masterComponentHosts.filterProperty('component', 'HBASE_MASTER').length;
    components.forEach(function (component) {
      var mc = localDB.masterComponentHosts.findProperty('component', component);
      if (mc) {
        if (!hosts.contains(mc.hostName)) {
          hosts.push(mc.hostName);
        }
      }
      else {
        var sc = localDB.slaveComponentHosts.findProperty('componentName', component);
        if (sc) {
          sc.hosts.map(function (host) {
            if (!hosts.contains(host.hostName)) {
              hosts.push(host.hostName);
            }
          });
        }
      }
    });
    var clusterData = {
      cpu: 0,
      disk: 0,
      ram: 0,
      hBaseInstalled: hBaseInstalled
    };
    var host = hosts[0] && localDB.hosts[hosts[0]];
    if (host) {
      clusterData.cpu = parseInt(host.cpu);
      var length = 0;
      host.disk_info.forEach(function(disk) {
        //invalid mountpoints
        if (!(disk.mountpoint.startsWith('/home/') || disk.mountpoint.startsWith('/homes/') ||
        		disk.mountpoint.startsWith('/dev/') || disk.mountpoint.startsWith('/tmp/'))) {
          length++;
        }
      },this);
      clusterData.disk = length;
      clusterData.ram = Math.round(parseFloat(host.memory) / (1024 * 1024));
    }
    this.set('clusterData', clusterData);
  },

  /**
   * Verify clusterData - check if all properties are defined
   */
  clusterDataIsValid: function () {
    if (!this.get('clusterData')) return false;
    if (this.get('clusterData.ram') == null || this.get('clusterData.cpu') == null || this.get('clusterData.disk') == null || this.get('clusterData.hBaseInstalled') == null) return false;
    return true;
  }

});
<|endoftext|>


<commit_before>// @flow weak

import React from 'react';
import {
  applyRouterMiddleware,
  hashHistory,
  Router,
  Route,
  IndexRoute,
  IndexRedirect,
} from 'react-router';
import { useScroll } from 'react-router-scroll';
import { kebabCase, titleize } from 'docs/site/src/utils/helpers';
import AppFrame from '../components/AppFrame';
import AppContent from '../components/AppContent';
import MarkdownDocs from '../components/MarkdownDocs';
import Home from '../pages/Home';

/**
 * This lets us eager load the files ahead of time
 * and require them dynamically with webpack's context feature
 */
const docsContext = require.context(
  './../../../../docs',
  true,
  /^((?![\\/]site\/src\/demos|node_modules[\\/]).)*\.md$/,
);

const apiDocRoutes = docsContext.keys()
  .filter((n) => /^\.\/api\//.test(n))
  .map((path) => {
    const name = path.replace(/.*\//, '').replace('.md', '');
    return (
      <Route
        key={name}
        title={name}
        path={`/component-api/${kebabCase(name)}`}
        content={docsContext(path)}
        component={MarkdownDocs}
        nav
      />
    );
  });

const demosContext = require.context('../demos', true, /\.md$/);
const demoRoutes = demosContext.keys()
  .map((path) => {
    const name = path.replace(/.*\//, '').replace('.md', '');
    return (
      <Route
        key={name}
        title={titleize(name)}
        path={`/component-demos/${name}`}
        content={demosContext(path)}
        component={MarkdownDocs}
        nav
      />
    );
  });

export default function AppRouter() {
  return (
    <Router
      history={hashHistory}
      render={applyRouterMiddleware(useScroll())}
    >
      <Route title="Material Charts" path="/" component={AppFrame}>
        <IndexRoute dockDrawer component={Home} title={null} />
        <Route
          title="Getting Started"
          path="/getting-started"
          component={AppContent}
          nav
        >
          <IndexRedirect to="installation" />
          <Route
            title="Installation"
            path="/getting-started/installation"
            content={docsContext('./getting-started/installation.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Usage"
            path="/getting-started/usage"
            content={docsContext('./getting-started/usage.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Server Rendering"
            path="/getting-started/server-rendering"
            content={docsContext('./getting-started/server-rendering.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Examples"
            path="/getting-started/examples"
            content={docsContext('./getting-started/examples.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
        <Route
          title="Customization"
          path="/customization"
          nav
          component={AppContent}
        >
          <IndexRedirect to="themes" />
          <Route
            title="Themes"
            path="/customization/themes"
            content={docsContext('./customization/themes.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Composition"
            path="/customization/composition"
            content={docsContext('./customization/composition.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
        <Route
          title="Style"
          path="/style"
          nav
          component={AppContent}
        >
          <Route
            title="Icons"
            path="/style/icons"
            content={docsContext('./site/src/pages/style/icons/icons.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Typography"
            path="/style/typography"
            content={docsContext('./site/src/pages/style/typography/typography.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
        <Route
          title="Layout"
          path="/layout"
          nav
          component={AppContent}
        >
          <Route
            title="Responsive UI"
            path="/layout/responsive-ui"
            content={docsContext('./site/src/pages/layout/responsive-ui/responsive-ui.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
        <Route
          title="Component Demos"
          path="/component-demos"
          nav
          component={AppContent}
        >
          {demoRoutes}
        </Route>
        <Route
          title="Component API"
          path="/component-api"
          nav
          component={AppContent}
        >
          {apiDocRoutes}
        </Route>
        <Route
          title="Discover More"
          path="/discover-more"
          nav
          component={AppContent}
        >
          <IndexRedirect to="community" />
          <Route
            title="Community"
            path="/discover-more/community"
            content={docsContext('./discover-more/community.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Showcase"
            path="/discover-more/showcase"
            content={docsContext('./discover-more/showcase.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Related Projects"
            path="/discover-more/related-projects"
            content={docsContext('./discover-more/related-projects.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
      </Route>
    </Router>
  );
}
<commit_msg>remove layout section from router<commit_after>// @flow weak

import React from 'react';
import {
  applyRouterMiddleware,
  hashHistory,
  Router,
  Route,
  IndexRoute,
  IndexRedirect,
} from 'react-router';
import { useScroll } from 'react-router-scroll';
import { kebabCase, titleize } from 'docs/site/src/utils/helpers';
import AppFrame from '../components/AppFrame';
import AppContent from '../components/AppContent';
import MarkdownDocs from '../components/MarkdownDocs';
import Home from '../pages/Home';

/**
 * This lets us eager load the files ahead of time
 * and require them dynamically with webpack's context feature
 */
const docsContext = require.context(
  './../../../../docs',
  true,
  /^((?![\\/]site\/src\/demos|node_modules[\\/]).)*\.md$/,
);

const apiDocRoutes = docsContext.keys()
  .filter((n) => /^\.\/api\//.test(n))
  .map((path) => {
    const name = path.replace(/.*\//, '').replace('.md', '');
    return (
      <Route
        key={name}
        title={name}
        path={`/component-api/${kebabCase(name)}`}
        content={docsContext(path)}
        component={MarkdownDocs}
        nav
      />
    );
  });

const demosContext = require.context('../demos', true, /\.md$/);
const demoRoutes = demosContext.keys()
  .map((path) => {
    const name = path.replace(/.*\//, '').replace('.md', '');
    return (
      <Route
        key={name}
        title={titleize(name)}
        path={`/component-demos/${name}`}
        content={demosContext(path)}
        component={MarkdownDocs}
        nav
      />
    );
  });

export default function AppRouter() {
  return (
    <Router
      history={hashHistory}
      render={applyRouterMiddleware(useScroll())}
    >
      <Route title="Material Charts" path="/" component={AppFrame}>
        <IndexRoute dockDrawer component={Home} title={null} />
        <Route
          title="Getting Started"
          path="/getting-started"
          component={AppContent}
          nav
        >
          <IndexRedirect to="installation" />
          <Route
            title="Installation"
            path="/getting-started/installation"
            content={docsContext('./getting-started/installation.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Usage"
            path="/getting-started/usage"
            content={docsContext('./getting-started/usage.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Server Rendering"
            path="/getting-started/server-rendering"
            content={docsContext('./getting-started/server-rendering.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Examples"
            path="/getting-started/examples"
            content={docsContext('./getting-started/examples.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
        <Route
          title="Customization"
          path="/customization"
          nav
          component={AppContent}
        >
          <IndexRedirect to="themes" />
          <Route
            title="Themes"
            path="/customization/themes"
            content={docsContext('./customization/themes.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Composition"
            path="/customization/composition"
            content={docsContext('./customization/composition.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
        <Route
          title="Style"
          path="/style"
          nav
          component={AppContent}
        >
          <Route
            title="Icons"
            path="/style/icons"
            content={docsContext('./site/src/pages/style/icons/icons.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Typography"
            path="/style/typography"
            content={docsContext('./site/src/pages/style/typography/typography.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
        <Route
          title="Component Demos"
          path="/component-demos"
          nav
          component={AppContent}
        >
          {demoRoutes}
        </Route>
        <Route
          title="Component API"
          path="/component-api"
          nav
          component={AppContent}
        >
          {apiDocRoutes}
        </Route>
        <Route
          title="Discover More"
          path="/discover-more"
          nav
          component={AppContent}
        >
          <IndexRedirect to="community" />
          <Route
            title="Community"
            path="/discover-more/community"
            content={docsContext('./discover-more/community.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Showcase"
            path="/discover-more/showcase"
            content={docsContext('./discover-more/showcase.md')}
            component={MarkdownDocs}
            nav
          />
          <Route
            title="Related Projects"
            path="/discover-more/related-projects"
            content={docsContext('./discover-more/related-projects.md')}
            component={MarkdownDocs}
            nav
          />
        </Route>
      </Route>
    </Router>
  );
}
<|endoftext|>


<commit_before>var HID = require('node-hid');

var VENDOR_ID = 0x27B8;
var PRODUCT_ID = 0x01ED;

var REPORT_ID = 1;
var REPORT_LENGTH = 9;

var _blink1HIDdevices = function() {
  return HID.devices(VENDOR_ID, PRODUCT_ID);
};

var devices = function() {
  var serialNumbers = [];

  _blink1HIDdevices().forEach(function(device) {
    serialNumbers.push(device.serialNumber);
  });

  return serialNumbers;
};

function Blink1(serialNumber) {
  var blink1HIDdevices = _blink1HIDdevices();

  if (blink1HIDdevices.length === 0) {
    throw new Error('No blink(1)\'s could be found');
  }

  var blink1HIDdevicePath = null;

  if (serialNumber === undefined) {
    serialNumber =  blink1HIDdevices[0].serialNumber;
  }

  blink1HIDdevices.some(function(blink1HIDdevice) {
    if (serialNumber === blink1HIDdevice.serialNumber) {
      blink1HIDdevicePath = blink1HIDdevice.path;
    }

    return (blink1HIDdevicePath !== null);
  });

  if (blink1HIDdevicePath === null) {
    throw new Error('No blink(1)\'s with serial number ' + serialNumber + ' could be found');
  }

  this.serialNumber = serialNumber;
  this.hidDevice = new HID.HID(blink1HIDdevicePath);
}

Blink1.prototype._sendCommand = function(/* command [, args ...]*/) {
  var featureReport = [REPORT_ID, 0, 0, 0, 0, 0, 0, 0, 0];

  featureReport[1] = arguments[0].charCodeAt(0);

  for (var i = 1; i < arguments.length; i++) {
    featureReport[i + 1] = arguments[i];
  }

  this.hidDevice.sendFeatureReport(featureReport);
};

Blink1.prototype._isValidCallback = function(callback) {
  return (typeof callback === 'function');
};

Blink1.prototype._validateNumber = function(number, name, min, max) {
  if (typeof number !== 'number') {
    throw new Error(name + ' must be a number');
  }

  if (number < min || number > max) {
    throw new Error(name + ' must be between ' + min + ' and ' + max);
  }
};

Blink1.prototype._validateAddress = function(address) {
  this._validateNumber(address, 'address', 0, 0xffff);
};

Blink1.prototype._validateValue = function(value) {
  this._validateNumber(value, 'value', 0, 0xff);
};

Blink1.prototype._validateCount = function(value) {
  this._validateNumber(value, 'count', 0, 0xff);
};

Blink1.prototype._validateFadeMillis = function(fadeMillis) {
  this._validateNumber(fadeMillis, 'fadeMillis', 0, 0x9FFF6);
};

Blink1.prototype._validateRGB = function(r, g, b) {
  this._validateNumber(r, 'r', 0, 0xff);
  this._validateNumber(g, 'g', 0, 0xff);
  this._validateNumber(b, 'b', 0, 0xff);
};

Blink1.prototype._validateMillis = function(millis) {
  this._validateNumber(millis, 'millis', 0, 0x9FFF6);
};

Blink1.prototype._validateMk2Position = function(position) {
  this._validateNumber(position, 'position', 0, 31);
};

Blink1.prototype._validateIndex = function(index) {
  this._validateNumber(index, 'index', 0, 2);
};

Blink1.prototype._readResponse = function(callback) {
  if (this._isValidCallback(callback)) {
    callback.apply(this, [this.hidDevice.getFeatureReport(REPORT_ID, REPORT_LENGTH)]);
  }
};

Blink1.prototype.degamma = function(n) {
  return Math.floor(((1 << Math.floor(n / 32)) - 1) +
          Math.floor((1 << Math.floor(n / 32)) * Math.floor((n % 32) + 1) + 15) / 32);
};

Blink1.prototype.fadeToRGB = function(fadeMillis, r, g, b, index, nogamma, callback) {
  this._validateFadeMillis(fadeMillis);
  this._validateRGB(r, g, b);

  var dms = fadeMillis / 10;

  // time component cant be 0
  if( dms === 0 )
	dms = 1;

  if (this._isValidCallback(index)) {
    // backwards compatible API, no index
    callback = index;
    index = 0;
  } else if (index === undefined) {
    index = 0;
  }

  this._validateIndex(index);

  var cr = nogamma ? r : this.degamma(r);
  var cg = nogamma ? g : this.degamma(g);
  var cb = nogamma ? b : this.degamma(b);

  this._sendCommand('c', cr, cg, cb, dms >> 8, dms % 0xff, index);

  if(this._isValidCallback(callback)) {
    setTimeout(callback, fadeMillis);
  }
};

Blink1.prototype.setRGB = function(r, g, b, index, nogamma, callback) {
  this._validateRGB(r, g, b);
  this._validateIndex(index);

  var cr = nogamma ? r : this.degamma(r);
  var cg = nogamma ? g : this.degamma(g);
  var cb = nogamma ? b : this.degamma(b);

  this._sendCommand('n', cr, cg, cb, 0, 0, index);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.readCurrentRGB = function(ledn, callback) {
  this._validateIndex(ledn);

  this._sendCommand('r', ledn, 0, 0, 0, 0, ledn);

  this._readResponse(function(response) {
    var value = {
      r: response[2],
      g: response[3],
      b: response[4],
      ledn: response[7]
    };

    if(this._isValidCallback(callback)) {
      callback(value);
    }
  });
};

Blink1.prototype._serverDown = function(on, millis, callback) {
  var dms = millis / 10;

  this._sendCommand('D', on, dms >> 8, dms % 0xff);

  if(this._isValidCallback(callback)) {
    setTimeout(callback, millis);
  }
};

/*Blink1.prototype.enableServerDown = function(millis, callback) {
  this._validateMillis(millis);

  this._serverDown(1, millis, callback);
};

Blink1.prototype.disableServerDown = function(millis, callback) {
  this._validateMillis(millis);

  this._serverDown(0, millis, callback);
};
*/

Blink1.prototype._playLoop = function(play, position, endPosition, count, callback) {
  this._sendCommand('p', play, position, endPosition, count);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.playLoop = function(startPosition, endPosition, count, callback) {
  this._validateMk2Position(startPosition);
  this._validateMk2Position(endPosition);
  this._validateCount(count);

  this._playLoop(1, startPosition, endPosition, count, callback);
};

/*
Blink1.prototype._play = function(play, position, callback) {
  this._sendCommand('p', play, position);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.play = function(position, callback) {
  this._validateMk2Position(position);

  this._play(1, position, callback);
};

Blink1.prototype.pause = function(callback) {
  this._play(0, 0, callback);
};*/

Blink1.prototype.readPlayState = function(callback) {
  this._sendCommand('S');

  this._readResponse(function(response) {
    var value = {
      playing: response[2],
      playstart: response[3],
      playend: response[4],
      playcount: response[5],
      playpos: response[6]
    };

    if(this._isValidCallback(callback)) {
      callback(value);
    }
  });
};

Blink1.prototype.writePatternLine = function(fadeMillis, r, g, b, position, nogamma, callback) {
  this._validateFadeMillis(fadeMillis);
  this._validateRGB(r, g, b);
  this._validateMk2Position(position);

  var dms = fadeMillis / 10;

  var cr = nogamma ? r : this.degamma(r);
  var cg = nogamma ? g : this.degamma(g);
  var cb = nogamma ? b : this.degamma(b);

  this._sendCommand('P', cr, cg, cb, dms >> 8, dms % 0xff, position, 0);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.persistPatternLine = function(callback) {
  this._sendCommand('W', 0xBE, 0xEF, 0xCA, 0xFE);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.readPatternLine = function(position, callback) {
  this._validateMk2Position(position);

  this._sendCommand('R', 0, 0, 0, 0, 0, position, 0);

  this._readResponse(function(response) {
    var value = {
      r: response[2],
      g: response[3],
      b: response[4],
      fadeMillis: ((response[5] << 8) + (response[6] & 0xff)) * 10,
      ledn: response[7]
    };

    if(this._isValidCallback(callback)) {
      callback(value);
    }
  });
};

Blink1.prototype.setLed = function(ledn, callback) {
  this._validateIndex(ledn);
  this._sendCommand('l', ledn);
  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.version = function(callback) {
  this._sendCommand('v');

  this._readResponse(function(response) {
    var version = String.fromCharCode(response[3]) + '.' + String.fromCharCode(response[4]);

    if(this._isValidCallback(callback)) {
      callback(version);
    }
  });
};

Blink1.prototype.close = function(callback) {
	this.hidDevice.close();

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.devices = devices;

module.exports = Blink1;
module.exports.Blink1 = Blink1; // backwards compatibility with older version
<commit_msg>use option parameter instead of multiple parameters<commit_after>var HID = require('node-hid');

var VENDOR_ID = 0x27B8;
var PRODUCT_ID = 0x01ED;

var REPORT_ID = 1;
var REPORT_LENGTH = 9;

var _blink1HIDdevices = function() {
  return HID.devices(VENDOR_ID, PRODUCT_ID);
};

var devices = function() {
  var serialNumbers = [];

  _blink1HIDdevices().forEach(function(device) {
    serialNumbers.push(device.serialNumber);
  });

  return serialNumbers;
};

function Blink1(serialNumber) {
  var blink1HIDdevices = _blink1HIDdevices();

  if (blink1HIDdevices.length === 0) {
    throw new Error('No blink(1)\'s could be found');
  }

  var blink1HIDdevicePath = null;

  if (serialNumber === undefined) {
    serialNumber =  blink1HIDdevices[0].serialNumber;
  }

  blink1HIDdevices.some(function(blink1HIDdevice) {
    if (serialNumber === blink1HIDdevice.serialNumber) {
      blink1HIDdevicePath = blink1HIDdevice.path;
    }

    return (blink1HIDdevicePath !== null);
  });

  if (blink1HIDdevicePath === null) {
    throw new Error('No blink(1)\'s with serial number ' + serialNumber + ' could be found');
  }

  this.serialNumber = serialNumber;
  this.hidDevice = new HID.HID(blink1HIDdevicePath);
}

Blink1.prototype._sendCommand = function(/* command [, args ...]*/) {
  var featureReport = [REPORT_ID, 0, 0, 0, 0, 0, 0, 0, 0];

  featureReport[1] = arguments[0].charCodeAt(0);

  for (var i = 1; i < arguments.length; i++) {
    featureReport[i + 1] = arguments[i];
  }

  this.hidDevice.sendFeatureReport(featureReport);
};

Blink1.prototype._isValidCallback = function(callback) {
  return (typeof callback === 'function');
};

Blink1.prototype._getCallback(opt) {
  if(!opt) {
    return opt;
  }
  if(this._isValidCallback(opt)) {
    return opt;
  }
  return opt.callback;
}

Blink1.prototype._validateNumber = function(number, name, min, max) {
  if (typeof number !== 'number') {
    throw new Error(name + ' must be a number');
  }

  if (number < min || number > max) {
    throw new Error(name + ' must be between ' + min + ' and ' + max);
  }
};

Blink1.prototype._validateAddress = function(address) {
  this._validateNumber(address, 'address', 0, 0xffff);
};

Blink1.prototype._validateValue = function(value) {
  this._validateNumber(value, 'value', 0, 0xff);
};

Blink1.prototype._validateCount = function(value) {
  this._validateNumber(value, 'count', 0, 0xff);
};

Blink1.prototype._validateFadeMillis = function(fadeMillis) {
  this._validateNumber(fadeMillis, 'fadeMillis', 0, 0x9FFF6);
};

Blink1.prototype._validateRGB = function(r, g, b) {
  this._validateNumber(r, 'r', 0, 0xff);
  this._validateNumber(g, 'g', 0, 0xff);
  this._validateNumber(b, 'b', 0, 0xff);
};

Blink1.prototype._validateMillis = function(millis) {
  this._validateNumber(millis, 'millis', 0, 0x9FFF6);
};

Blink1.prototype._validateMk2Position = function(position) {
  this._validateNumber(position, 'position', 0, 31);
};

Blink1.prototype._validateIndex = function(index) {
  this._validateNumber(index, 'index', 0, 2);
};

Blink1.prototype._readResponse = function(callback) {
  if (this._isValidCallback(callback)) {
    callback.apply(this, [this.hidDevice.getFeatureReport(REPORT_ID, REPORT_LENGTH)]);
  }
};

Blink1.prototype.degamma = function(n) {
  return Math.floor(((1 << Math.floor(n / 32)) - 1) +
          Math.floor((1 << Math.floor(n / 32)) * Math.floor((n % 32) + 1) + 15) / 32);
};

Blink1.prototype.fadeToRGB = function(fadeMillis, r, g, b, index, nogamma, callback) {
  this._validateFadeMillis(fadeMillis);
  this._validateRGB(r, g, b);

  var dms = fadeMillis / 10;

  // time component cant be 0
  if( dms === 0 )
	dms = 1;

  if (this._isValidCallback(index)) {
    // backwards compatible API, no index
    callback = index;
    index = 0;
  } else if (index === undefined) {
    index = 0;
  }

  this._validateIndex(index);

  var cr = nogamma ? r : this.degamma(r);
  var cg = nogamma ? g : this.degamma(g);
  var cb = nogamma ? b : this.degamma(b);

  this._sendCommand('c', cr, cg, cb, dms >> 8, dms % 0xff, index);

  if(this._isValidCallback(callback)) {
    setTimeout(callback, fadeMillis);
  }
};

Blink1.prototype.setRGB = function(r, g, b, index, nogamma, callback) {
  this._validateRGB(r, g, b);
  this._validateIndex(index);

  var cr = nogamma ? r : this.degamma(r);
  var cg = nogamma ? g : this.degamma(g);
  var cb = nogamma ? b : this.degamma(b);

  this._sendCommand('n', cr, cg, cb, 0, 0, index);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.readCurrentRGB = function(ledn, callback) {
  this._validateIndex(ledn);

  this._sendCommand('r', ledn, 0, 0, 0, 0, ledn);

  this._readResponse(function(response) {
    var value = {
      r: response[2],
      g: response[3],
      b: response[4],
      ledn: response[7]
    };

    if(this._isValidCallback(callback)) {
      callback(value);
    }
  });
};

Blink1.prototype._serverDown = function(on, millis, callback) {
  var dms = millis / 10;

  this._sendCommand('D', on, dms >> 8, dms % 0xff);

  if(this._isValidCallback(callback)) {
    setTimeout(callback, millis);
  }
};

/*Blink1.prototype.enableServerDown = function(millis, callback) {
  this._validateMillis(millis);

  this._serverDown(1, millis, callback);
};

Blink1.prototype.disableServerDown = function(millis, callback) {
  this._validateMillis(millis);

  this._serverDown(0, millis, callback);
};
*/

Blink1.prototype._playLoop = function(play, position, endPosition, count, callback) {
  this._sendCommand('p', play, position, endPosition, count);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.playLoop = function(startPosition, endPosition, count, callback) {
  this._validateMk2Position(startPosition);
  this._validateMk2Position(endPosition);
  this._validateCount(count);

  this._playLoop(1, startPosition, endPosition, count, callback);
};

/*
Blink1.prototype._play = function(play, position, callback) {
  this._sendCommand('p', play, position);

  if(this._isValidCallback(callback)) {
    callback();
  }
};

Blink1.prototype.play = function(position, callback) {
  this._validateMk2Position(position);

  this._play(1, position, callback);
};

Blink1.prototype.pause = function(callback) {
  this._play(0, 0, callback);
};*/

Blink1.prototype.readPlayState = function(opt) {
  this._sendCommand('S');

  this._readResponse(function(response) {
    var value = {
      playing: response[2],
      playstart: response[3],
      playend: response[4],
      playcount: response[5],
      playpos: response[6]
    };

    var cb = this._getCallback(opt);
    if(cb) {
      cb(value);
    }
  });
};

Blink1.prototype.writePatternLine = function(opt) {
  if(!opt)
    opt={};
  var fadeMillis = opt.fadeMillis || 0;
  var r = opt.r || 0;
  var g = opt.g || 0;
  var b = opt.b || 0;
  var lineIndex = opt.lineIndex || 0;
  var gammaAdjust = opt.gammaAdjust || false;

  this._validateFadeMillis(fadeMillis);
  this._validateRGB(r, g, b);
  this._validateMk2Position(lineIndex);

  var dms = fadeMillis / 10;

  var cr = gammaAdjust ? r : this.degamma(r);
  var cg = gammaAdjust ? g : this.degamma(g);
  var cb = gammaAdjust ? b : this.degamma(b);

  this._sendCommand('P', cr, cg, cb, dms >> 8, dms % 0xff, lineIndex);

  var cb = this._getCallback(opt);
  if(cb) {
    cb();
  }
};

Blink1.prototype.persistPatternLine = function(opt) {
  this._sendCommand('W', 0xBE, 0xEF, 0xCA, 0xFE);

  var cb = this._getCallback(opt);
  if(cb) {
    cb();
  }
};

Blink1.prototype.readPatternLine = function(opt) {
  if(!opt)
    opt={};
  var position = opt.position || 0;
  this._validateMk2Position(position);

  this._sendCommand('R', 0, 0, 0, 0, 0, position, 0);

  this._readResponse(function(response) {
    var value = {
      r: response[2],
      g: response[3],
      b: response[4],
      fadeMillis: ((response[5] << 8) + (response[6] & 0xff)) * 10,
      ledn: response[7]
    };

    var cb = this._getCallback(opt);
    if(cb) {
      cb(value);
    }
  });
};

Blink1.prototype.setLed = function(opt) {
  if(!opt)
    opt={};
  var ledn = opt.ledn || 0;
  this._validateIndex(ledn);
  this._sendCommand('l', ledn);
  var cb = this._getCallback(opt);
  if(cb) {
    cb();
  }
};

Blink1.prototype.version = function(opt) {
  this._sendCommand('v');

  this._readResponse(function(response) {
    var version = String.fromCharCode(response[3]) + '.' + String.fromCharCode(response[4]);
    var cb = this._getCallback(opt);
    if(cb) {
      cb(version);
    }
  });
};

Blink1.prototype.close = function(opt) {
  this.hidDevice.close();

  var cb = this._getCallback(opt);
    if(cb) {
      cb(version);
    }
};

Blink1.devices = devices;

module.exports = Blink1;
module.exports.Blink1 = Blink1; // backwards compatibility with older version
<|endoftext|>


<commit_before>import draw2d from "draw2d";

// Label which has centered text and specified width
export default class Label extends draw2d.shape.basic.Text {
    textWidth = 0
    constructor(textWidth, attr, getter, setter) {
        super(attr, getter, setter)
        this.textWidth = textWidth
    }

    calculateTextAttr() {
        let attr = {
            "text-anchor": "middle",
            "font-size": this.fontSize,
            "font-weight": (this.bold === true) ? "bold" : "normal",
            fill: this.fontColor.rgba(),
            stroke: this.outlineColor.rgba(),
            "stroke-width": this.outlineStroke,
        }
        if (this.fontFamily !== null) {
            attr["font-family"] = this.fontFamily
        }
        return attr
    }

    setTextWidth(textWidth) {
        // Force re-calculate of text width
        this.cachedWrappedAttr = null
        this.textWidth = textWidth
    }

    repaint(attributes) {
        if (this.repaintBlocked === true || this.shape === null) {
            return
        }

        this.svgNodes.attr({ ...this.calculateTextAttr(), ...this.wrappedTextAttr(this.text, this.getWidth() - this.padding.left - this.padding.right) })

        // set of the x/y must be done AFTER the font-size and bold has been set.
        // Reason: the getHeight method needs the font-size for calculation because
        //         it redirects the calculation to the SVG element.
        this.svgNodes.attr({ x: this.getWidth() / 2, y: this.getHeight() / 2 })

        // this is an exception call. Don't call the super method (Label) to avoid
        // the calculation in this method.
        draw2d.SetFigure.prototype.repaint.call(this, attributes)
    }

    wrappedTextAttr(text, width) {
        let words = text.split(" ")
        if (this.canvas === null || words.length === 0) {
            return { text: text, width: width, height: 20 }
        }

        if (this.cachedWrappedAttr === null) {
            let abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            let svgText = this.canvas.paper.text(0, 0, "").attr({ ...this.calculateTextAttr(), ...{ text: abc } })

            // get a good estimation of a letter width...not correct but this is working for the very first draft implementation
            let letterWidth = svgText.getBBox(true).width / abc.length

            let s = [words[0]], x = s[0].length * letterWidth
            let w = null
            for (let i = 1; i < words.length; i++) {
                w = words[i]
                let l = w.length * letterWidth
                if ((x + l) > this.textWidth) {
                    s.push("\n")
                    x = l
                } else {
                    s.push(" ")
                    x += l
                }
                s.push(w)
            }

            // set the wrapped text and get the resulted bounding box
            svgText.attr({ text: s.join("") })
            let bbox = svgText.getBBox(true)
            svgText.remove()
            this.cachedWrappedAttr = {
                text: s.join(""),
                width: (Math.max(width, bbox.width) + this.padding.left + this.padding.right),
                height: (bbox.height + this.padding.top + this.padding.bottom)
            }
        }
        return this.cachedWrappedAttr
    }
}<commit_msg>Support ; and [ as new lines in labels<commit_after>import draw2d from "draw2d";

// Label which has centered text and specified width
export default class Label extends draw2d.shape.basic.Text {
    textWidth = 0
    constructor(textWidth, attr, getter, setter) {
        super(attr, getter, setter)
        this.textWidth = textWidth
    }

    calculateTextAttr() {
        let attr = {
            "text-anchor": "middle",
            "font-size": this.fontSize,
            "font-weight": (this.bold === true) ? "bold" : "normal",
            fill: this.fontColor.rgba(),
            stroke: this.outlineColor.rgba(),
            "stroke-width": this.outlineStroke,
        }
        if (this.fontFamily !== null) {
            attr["font-family"] = this.fontFamily
        }
        return attr
    }

    setTextWidth(textWidth) {
        // Force re-calculate of text width
        this.cachedWrappedAttr = null
        this.textWidth = textWidth
    }

    repaint(attributes) {
        if (this.repaintBlocked === true || this.shape === null) {
            return
        }

        this.svgNodes.attr({ ...this.calculateTextAttr(), ...this.wrappedTextAttr(this.text, this.getWidth() - this.padding.left - this.padding.right) })

        // set of the x/y must be done AFTER the font-size and bold has been set.
        // Reason: the getHeight method needs the font-size for calculation because
        //         it redirects the calculation to the SVG element.
        this.svgNodes.attr({ x: this.getWidth() / 2, y: this.getHeight() / 2 })

        // this is an exception call. Don't call the super method (Label) to avoid
        // the calculation in this method.
        draw2d.SetFigure.prototype.repaint.call(this, attributes)
    }

    wrappedTextAttr(text, width) {
        let words = text.replace(';', ' ; ').split(" ")
        if (this.canvas === null || words.length === 0) {
            return { text: text, width: width, height: 20 }
        }

        if (this.cachedWrappedAttr === null) {
            let abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            let svgText = this.canvas.paper.text(0, 0, "").attr({ ...this.calculateTextAttr(), ...{ text: abc } })

            // get a good estimation of a letter width...not correct but this is working for the very first draft implementation
            let letterWidth = svgText.getBBox(true).width / abc.length

            let s = []
            let x = 0
            let w = null
            for (let i = 0; i < words.length; i++) {
                w = words[i]
                let isStart = false

                if (w.startsWith(';')) {
                    w = w.substr(1)
                    isStart = true
                }

                let l = w.length * letterWidth
                if (isStart || w.startsWith('[')) {
                    s.push("\n")
                    x = l
                }

                if ((x + l) > this.textWidth) {
                    s.push("\n")
                    x = l
                } else {
                    s.push(" ")
                    x += l
                }

                s.push(w)
            }

            // set the wrapped text and get the resulted bounding box
            svgText.attr({ text: s.join("") })
            let bbox = svgText.getBBox(true)
            svgText.remove()
            this.cachedWrappedAttr = {
                text: s.join(""),
                width: (Math.max(width, bbox.width) + this.padding.left + this.padding.right),
                height: (bbox.height + this.padding.top + this.padding.bottom)
            }
        }
        return this.cachedWrappedAttr
    }
}<|endoftext|>


<commit_before>ManageIQ.angular.app.component('vmCloudAddSecurityGroup', {
  bindings: {
    recordId: '@',
    redirectUrl: '@',
  },
  controllerAs: 'vm',
  controller: vmCloudAddSecurityGroupFormController,
  templateUrl: '/static/vm_cloud/add_security_group.html.haml',
});

vmCloudAddSecurityGroupFormController.$inject = ['API', 'miqService', '$q'];

function vmCloudAddSecurityGroupFormController(API, miqService, $q) {
  var vm = this;

  vm.$onInit = function() {
    vm.afterGet = false;
    vm.vmCloudModel = {
      security_group: '',
    };
    vm.security_groups = [];
    vm.formId = vm.recordId;
    vm.saveable = miqService.saveable;
    vm.newRecord = true;
    miqService.sparkleOn();

    var currentSecurityGroups;

    $q.all([
      API.get('/api/instances/' + vm.recordId),
      API.get('/api/instances/' + vm.recordId + '/security_groups?expand=resources&attributes=id,name'),
    ])
      .then(function(data) {
        var tenantId = data[0].cloud_tenant_id;
        currentSecurityGroups = data[1].resources;

        return API.get('/api/cloud_tenants/' + tenantId + '/security_groups?expand=resources&attributes=id,name');
      })
      .then(function(data) {
        vm.security_groups = data.resources.filter(function(securityGroup) {
          return !_.find(currentSecurityGroups, { id: securityGroup.id });
        });

        vm.afterGet = true;
        miqService.sparkleOff();
      }).catch(miqService.handleFailure);
  };

  vm.cancelClicked = function() {
    miqService.sparkleOn();
    miqService.redirectBack(sprintf(__('Addition of security group was canceled by the user.')), 'warning', vm.redirectUrl);
  };

  vm.addClicked = function() {
    var saveObject = {
      name: vm.vmCloudModel.security_group,
      action: 'add',
    };
    var saveMsg = sprintf(__('%s has been successfully added.'), vm.vmCloudModel.security_group);
    miqService.sparkleOn();
    API.post('/api/instances/' + vm.recordId + '/security_groups/', saveObject)
      .then(miqService.redirectBack.bind(vm, saveMsg, 'success', vm.redirectUrl))
      .catch(miqService.handleFailure);
  };
}
<commit_msg>Display success flash message after canceling adding Security Group<commit_after>ManageIQ.angular.app.component('vmCloudAddSecurityGroup', {
  bindings: {
    recordId: '@',
    redirectUrl: '@',
  },
  controllerAs: 'vm',
  controller: vmCloudAddSecurityGroupFormController,
  templateUrl: '/static/vm_cloud/add_security_group.html.haml',
});

vmCloudAddSecurityGroupFormController.$inject = ['API', 'miqService', '$q'];

function vmCloudAddSecurityGroupFormController(API, miqService, $q) {
  var vm = this;

  vm.$onInit = function() {
    vm.afterGet = false;
    vm.vmCloudModel = {
      security_group: '',
    };
    vm.security_groups = [];
    vm.formId = vm.recordId;
    vm.saveable = miqService.saveable;
    vm.newRecord = true;
    miqService.sparkleOn();

    var currentSecurityGroups;

    $q.all([
      API.get('/api/instances/' + vm.recordId),
      API.get('/api/instances/' + vm.recordId + '/security_groups?expand=resources&attributes=id,name'),
    ])
      .then(function(data) {
        var tenantId = data[0].cloud_tenant_id;
        currentSecurityGroups = data[1].resources;

        return API.get('/api/cloud_tenants/' + tenantId + '/security_groups?expand=resources&attributes=id,name');
      })
      .then(function(data) {
        vm.security_groups = data.resources.filter(function(securityGroup) {
          return !_.find(currentSecurityGroups, { id: securityGroup.id });
        });

        vm.afterGet = true;
        miqService.sparkleOff();
      }).catch(miqService.handleFailure);
  };

  vm.cancelClicked = function() {
    miqService.sparkleOn();
    miqService.redirectBack(sprintf(__('Addition of security group was canceled by the user.')), 'success', vm.redirectUrl);
  };

  vm.addClicked = function() {
    var saveObject = {
      name: vm.vmCloudModel.security_group,
      action: 'add',
    };
    var saveMsg = sprintf(__('%s has been successfully added.'), vm.vmCloudModel.security_group);
    miqService.sparkleOn();
    API.post('/api/instances/' + vm.recordId + '/security_groups/', saveObject)
      .then(miqService.redirectBack.bind(vm, saveMsg, 'success', vm.redirectUrl))
      .catch(miqService.handleFailure);
  };
}
<|endoftext|>


<commit_before>
$(function() {
	initDatepicker();
});

// initiate the datepicker
function initDatepicker(){
	locale = $('html').attr('lang');
	$.datepicker.setDefaults($.datepicker.regional[locale]);
	$('.datepicker').each(function(){
	 $(this).datepicker({
		altField : "#" + replaceId($(this).attr('id')) + "_alt",
		altFormat : "yy-mm-dd",
		gotoCurrent : true,
		onSelect : function() {
		triggerOnValidDate(getMode(), $(this));
		},
		clickInput:true,
		changeMonth : true,
		changeYear : true,
		yearRange : '1970:2040',
		firstDay : 1,
		autoclose:true,
	}).on('keyup',function(){
		//$(this).datepicker('hide');
		 eventTrigger($(this),event);
	});
	});
}

// this will be triggered when user want to put date manually
function eventTrigger($element,event){
	convertedId = replaceId($element.attr('id'));
	$altFiledInput = $("#" + convertedId + "_alt");
	var date = '';
	if((event.which != 37) && (event.which != 38) && (event.which != 39) && (event.which != 40)){
	try {
		switch (locale) {
		case 'de':
			date = $.datepicker.parseDate('dd.mm.yy', $element.val());
			break;
		case 'en':
			date = $.datepicker.parseDate('mm/dd/yy', $element.val());
			break;
		default:
			break;
		}
		var day='';
		var month='';
		var tempMonthValue=(date.getMonth()+1);
		var year ='';

		// set date format to a compatible iso form
		if((date.getDate() <= 9) &&(getMode==='modify')){
			day = ("0" + (date.getDate())).slice(-2);
		}else{
			day = date.getDate();
		}
		if((tempMonthValue <= 9)&&(getMode==='modify')){
			month = ("0" + tempMonthValue).slice(-2);
		}else{
			month = tempMonthValue;
		}
			correntDate = date.getFullYear() + '-' +month + '-' + day;
			$altFiledInput.val(correntDate);
			triggerOnValidDate(getMode(), $altFiledInput);
	} catch (e) {
		triggerOnInvalidDate(getMode(),$element);
	}}
}

// replace the dot in id attribute
function replaceId(oldId) {
	return oldId.replace(/\./g, "\\.");
}

function triggerOnValidDate(mode, element) {
	if (mode === 'modify') {
		VariableModifyForm.validate(element.closest("form"));
	} else {
		// number of characters in input field
		if(element.val().length === 10){
		variableSearch();
		}else{
			$altFiledInput.val('');
		}
	}
}

function triggerOnInvalidDate(mode, element) {
	if (mode === 'modify') {
		$altFiledInput.val('invalid date');
		VariableModifyForm.validate(element.closest("form"));
	} else {
		if (element.val() === '') {
			$altFiledInput.val('');
			variableSearch();
		}
	}
}
<commit_msg>#7 add comment to datepicker.js<commit_after>
$(function() {
	initDatepicker();
});

// initiate the datepicker
function initDatepicker(){
	locale = $('html').attr('lang');
	$.datepicker.setDefaults($.datepicker.regional[locale]);
	$('.datepicker').each(function(){
	 $(this).datepicker({
		altField : "#" + replaceId($(this).attr('id')) + "_alt",
		altFormat : "yy-mm-dd",
		gotoCurrent : true,
		onSelect : function() {
		triggerOnValidDate(getMode(), $(this));
		},
		clickInput:true,
		changeMonth : true,
		changeYear : true,
		yearRange : '1970:2040',
		firstDay : 1,
		autoclose:true,
	}).on('keyup',function(){
		//$(this).datepicker('hide');
		 eventTrigger($(this),event);
	});
	});
}

// this will be triggered when user want to put date manually
function eventTrigger($element,event){
	convertedId = replaceId($element.attr('id'));
	$altFiledInput = $("#" + convertedId + "_alt");
	var date = '';
	// ignore event from keyup,keydown, keyleft and keyright
	if((event.which != 37) && (event.which != 38) && (event.which != 39) && (event.which != 40)){
	try {
		switch (locale) {
		case 'de':
			date = $.datepicker.parseDate('dd.mm.yy', $element.val());
			break;
		case 'en':
			date = $.datepicker.parseDate('mm/dd/yy', $element.val());
			break;
		default:
			break;
		}
		var day='';
		var month='';
		var tempMonthValue=(date.getMonth()+1);
		var year ='';

		// set date format to a compatible iso form
		if((date.getDate() <= 9) &&(getMode==='modify')){
			day = ("0" + (date.getDate())).slice(-2);
		}else{
			day = date.getDate();
		}
		if((tempMonthValue <= 9)&&(getMode==='modify')){
			month = ("0" + tempMonthValue).slice(-2);
		}else{
			month = tempMonthValue;
		}
			correntDate = date.getFullYear() + '-' +month + '-' + day;
			$altFiledInput.val(correntDate);
			triggerOnValidDate(getMode(), $altFiledInput);
	} catch (e) {
		triggerOnInvalidDate(getMode(),$element);
	}}
}

// replace the dot in id attribute
function replaceId(oldId) {
	return oldId.replace(/\./g, "\\.");
}

function triggerOnValidDate(mode, element) {
	if (mode === 'modify') {
		VariableModifyForm.validate(element.closest("form"));
	} else {
		// number of characters in input field
		if(element.val().length === 10){
		variableSearch();
		}else{
			$altFiledInput.val('');
		}
	}
}

function triggerOnInvalidDate(mode, element) {
	if (mode === 'modify') {
		$altFiledInput.val('invalid date');
		VariableModifyForm.validate(element.closest("form"));
	} else {
		if (element.val() === '') {
			$altFiledInput.val('');
			variableSearch();
		}
	}
}
<|endoftext|>


<commit_before>var mode = '';
function triggerDatepicker(id) {
	event.preventDefault();
	locale = $('html').attr('lang');
	mode = setmode();
	$.datepicker.setDefaults($.datepicker.regional[locale]);
	convertedId = replaceId(id);
	$element = $("#" + convertedId);
	$element.datepicker({
		altField : "#" + convertedId + "_alt",
		altFormat : "yy-mm-dd",
		gotoCurrent : true,
		onSelect : function() {
			triggerOnValidDate(mode, $element);
		},
		autoclose : true,
		changeMonth : true,
		changeYear : true,
		autoclose : true,
		yearRange : '1970:2040',
		firstDay : 1
	}).datepicker('show');
}
function triggerOnKeyup(id) {
	convertedId = replaceId(id);
	$element = $("#" + convertedId);
	$element.datepicker("hide");
	if (event.keyCode == 46) {
		$element.val('');
	}
	event.preventDefault();
	$altFiledInput = $("#" + convertedId + "_alt");
	var date = '';
	try {
		switch (locale) {
		case 'de':
			date = $.datepicker.parseDate('dd.mm.yy', $element.val());
			break;
		case 'en':
			date = $.datepicker.parseDate('mm/dd/yy', $element.val());
			break;
		default:
			break;
		}
		var day = ("0" + (date.getDate())).slice(-2);
		var year = date.getFullYear();
		// JavaScript months are 0-11
		var month = ("0" + (date.getMonth() + 1)).slice(-2);
		$altFiledInput.val(year + '-' + month + '-' + day);
		triggerOnValidDate(mode, $element);
	} catch (e) {
		triggerOnInvalidDate(mode, $element);
	}
}
function replaceId(oldId) {
	return oldId.replace(/\./g, "\\.");
}

function triggerOnValidDate(mode, element) {
	if (mode === 'modify') {
		VariableModifyForm.validate(element.closest("form"));
		$element.unbind('focus');
	} else {
		VariableSearchForm.search(element.closest("form"));
	}
}
function triggerOnInvalidDate(mode, element) {
	if (mode === 'modify') {
		$altFiledInput.val('invalid date');
		VariableModifyForm.validate(element.closest("form"));
	} else {
		if (element.val() === '') {
			$altFiledInput.val('');
			VariableSearchForm.search(element.closest("form"));
		}
	}
}<commit_msg>#7 fix the jshint test<commit_after>var mode = '';
function triggerDatepicker(id) {
	event.preventDefault();
	locale = $('html').attr('lang');
	mode = setmode();
	$.datepicker.setDefaults($.datepicker.regional[locale]);
	convertedId = replaceId(id);
	$element = $("#" + convertedId);
	$element.datepicker({
		altField : "#" + convertedId + "_alt",
		altFormat : "yy-mm-dd",
		gotoCurrent : true,
		onSelect : function() {
			triggerOnValidDate(mode, $element);
		},
		autoclose : true,
		changeMonth : true,
		changeYear : true,
		yearRange : '1970:2040',
		firstDay : 1
	}).datepicker('show');
}
function triggerOnKeyup(id) {
	convertedId = replaceId(id);
	$element = $("#" + convertedId);
	$element.datepicker("hide");
	if (event.keyCode == 46) {
		$element.val('');
	}
	event.preventDefault();
	$altFiledInput = $("#" + convertedId + "_alt");
	var date = '';
	try {
		switch (locale) {
		case 'de':
			date = $.datepicker.parseDate('dd.mm.yy', $element.val());
			break;
		case 'en':
			date = $.datepicker.parseDate('mm/dd/yy', $element.val());
			break;
		default:
			break;
		}
		var day = ("0" + (date.getDate())).slice(-2);
		var year = date.getFullYear();
		// JavaScript months are 0-11
		var month = ("0" + (date.getMonth() + 1)).slice(-2);
		$altFiledInput.val(year + '-' + month + '-' + day);
		triggerOnValidDate(mode, $element);
	} catch (e) {
		triggerOnInvalidDate(mode, $element);
	}
}
function replaceId(oldId) {
	return oldId.replace(/\./g, "\\.");
}

function triggerOnValidDate(mode, element) {
	if (mode === 'modify') {
		VariableModifyForm.validate(element.closest("form"));
		$element.unbind('focus');
	} else {
		VariableSearchForm.search(element.closest("form"));
	}
}
function triggerOnInvalidDate(mode, element) {
	if (mode === 'modify') {
		$altFiledInput.val('invalid date');
		VariableModifyForm.validate(element.closest("form"));
	} else {
		if (element.val() === '') {
			$altFiledInput.val('');
			VariableSearchForm.search(element.closest("form"));
		}
	}
}<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *  WSO2 Inc. licenses this file to you under the Apache License,
 *  Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
var $radio = $('.auto-submit-star');
var $btn = $('#btn-post');
var $textArea = $('#com-body');
var $stream = $('#stream');
var $firstReview = $('.com-first-review');
var $alert = $('.com-alert');
var $sort = $('.com-sort');
var $lastReview = $('.load-more');
var $more = $('#more');
var $empty_list = $('#empty_list');
var $reviews_frame = $("html");
var windowProxy;
var publish = function(activity, onSuccess) {
    if (activity.target) {
        activity.context = {
            "id": target
        };
    } else {
        activity.target = {
            "id": target
        };
    }
    debugger;
    var url = caramel.url('/apis/user-reviews');
    $.ajax({
        url: url,
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(activity),
        success: onSuccess
    });
    /*$.post(url, {
        activity: JSON.stringify(activity)
    }, onSuccess)*/
};
var showAlert = function(msg) {
    $alert.html(msg).fadeIn("fast").css('display', 'inline-block');
};
var showLoading = function(status) {
    if (status) {
        $alert.html('').css('display', 'inline-block').addClass('com-alert-wait');
    } else {
        $alert.hide().removeClass('com-alert-wait');
    }
};
$radio.rating({
    callback: function(value) {}
});
$btn.click(function(e) {
    e.preventDefault();
    var rating = Number($('input.star-rating-applied:checked').val());
    var review = $textArea.val();
    if (!review && !rating) {
        showAlert("Please add your Review and Rating");
    } else if (!review) {
        showAlert("Please add your Review");
    } else if (!rating) {
        showAlert("Please add your Rating");
    } else {
        var activity = {
            "verb": "post",
            "object": {
                "objectType": "review",
                "content": review,
                rating: rating,
                "likes": {
                    "totalItems": 0
                },
                "dislikes": {
                    "totalItems": 0
                }
            }
        };
        $btn.attr('disabled', 'disabled');
        showLoading(true);
        var pos = target.indexOf(':');
        var aid = target.substring(pos + 1);
        var type = target.substring(0, pos);
        var addAndRenderNew = function(successCallback) {
            $('#newest').addClass('selected');
            publish(activity, function(published) {
                if ($firstReview.length) {
                    $firstReview.hide();
                    $sort.removeClass('com-sort-hidden');
                }
                $btn.removeAttr('disabled');
                if (published.success) {
                    showLoading(false);
                    $radio.rating('select', null);
                    $textArea.val('');
                    activity.id = published.id;
                    //Remove carbon.super tenant domain from username
                    var pieces = user.split(/[\s@]+/);
                    if (pieces[pieces.length - 1] == 'carbon.super') {
                        user = pieces[pieces.length - 2];
                    }
                    activity.actor = {
                        id: user
                    };
                    usingTemplate(function(template) {
                        var newComment = template(activity);
                        $stream.prepend(newComment);
                        successCallback && successCallback();
                    });
                }
            });
        };
        addAndRenderNew(function() {
            redrawReviews();
        });
    }
});
$stream.on('click', '.icon-thumbs-down', function(e) {
    e.preventDefault();
    var $tDownBtn = $(e.target);
    var $review = $tDownBtn.parents('.com-review');
    var id = $review.attr('data-target-id');
    var $tDownCount = $review.find('.com-dislike-count');
    var activity = {
        target: {
            id: id
        },
        object: {}
    };
    var $opposite = $review.find('.icon-thumbs-up');
    if ($opposite.hasClass('selected')) {
        var ulikeActivity = {
            target: {
                id: id
            },
            object: {}
        };
        var $likeCount = $review.find('.com-like-count');
        ulikeActivity.verb = 'unlike';
        publish(ulikeActivity, function() {
            $likeCount.text((Number($likeCount.text()) - 1) || '');
        });
        $opposite.removeClass('selected');
    }
    if ($tDownBtn.hasClass('selected')) {
        activity.verb = 'undislike';
        publish(activity, function() {
            $tDownCount.text((Number($tDownCount.text()) - 1) || '');
        });
        $tDownBtn.removeClass('selected');
    } else {
        activity.verb = 'dislike';
        publish(activity, function() {
            $tDownCount.text(Number($tDownCount.text()) + 1);
        });
        $tDownBtn.addClass('selected');
    }
});
$stream.on('click', '.icon-thumbs-up', function(e) {
    e.preventDefault();
    var $tUpBtn = $(e.target);
    var $review = $tUpBtn.parents('.com-review');
    var id = $review.attr('data-target-id');
    var $likeCount = $review.find('.com-like-count');
    var activity = {
        target: {
            id: id
        },
        object: {}
    };
    var $opposite = $review.find('.icon-thumbs-down');
    if ($opposite.hasClass('selected')) {
        var uDislikeActivity = {
            target: {
                id: id
            },
            object: {}
        };
        var $uDislikeCount = $review.find('.com-dislike-count');
        uDislikeActivity.verb = 'undislike';
        publish(uDislikeActivity, function() {
            $uDislikeCount.text((Number($uDislikeCount.text()) - 1) || '');
        });
        $opposite.removeClass('selected');
    }
    if ($tUpBtn.hasClass('selected')) {
        activity.verb = 'unlike';
        publish(activity, function() {
            $likeCount.text((Number($likeCount.text()) - 1) || '');
        });
        $tUpBtn.removeClass('selected');
    } else {
        activity.verb = 'like';
        publish(activity, function() {
            $likeCount.text(Number($likeCount.text()) + 1);
        });
        $tUpBtn.addClass('selected');
    }
});
$more.on('click', '.load-more', function(e) {
    e.preventDefault();
    var offset = parseInt($('.load-more').attr("value"));
    var url = caramel.url('/apis/user-reviews');
    $.get(url, {
        target: target,
        sortBy: $('.com-sort .selected').attr('id'),
        offset: offset,
        limit: 10
    }, function(obj) {
        var reviews = obj || [];
        if (jQuery.isEmptyObject(reviews) || reviews.length < 10) {
            $more.hide();
            $empty_list.text("No more activities to retrieve.");
        }
        usingTemplate(function(template) {
            var str = "";
            for (var i = 0; i < reviews.length; i++) {
                var review = reviews[i];
                str += template(review);
            }
            $stream.append(str);
            //callback && callback();
            adjustHeight();
            $('.load-more').attr("value", parseInt(offset) + 10);
        });
    });
});
$stream.on('click', '#btn-delete', function(e) {
    e.preventDefault();
    var $deleteBtn = $(e.target);
    var $review = $deleteBtn.parents('.com-review');
    var id = $review.attr('data-target-id');
    var url = caramel.url('/apis/user-review/' + id);
    $.ajax({
        url: url,
        type: 'DELETE',
        success: function(obj) {
            if (obj.success) {
                $review.remove();
            }
        }
    });
});
$reviews_frame.niceScroll();
<commit_msg>Fix for STORE-1347 : Prevent user adding multiple reviews from UI , Improve UX to support one time review option<commit_after>/*
 *  Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *  WSO2 Inc. licenses this file to you under the Apache License,
 *  Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
var $container = $(".com-container");
var getTextArea = function () {
    return $('.com-container #com-body');
};
var getMyReviewElement = function () {
    return $('.com-container .my-review');
};
var $stream = $('#stream');
var $firstReview = $('.com-first-review');
var getAlertElement = function () {
    return $container.find('.com-alert');
};
var $loading = $('.com-container .row.com-add div[class^="loading-"]');
var $sort = $('.com-sort');
var $lastReview = $('.load-more');
var $more = $('#more');
var $empty_list = $('#empty_list');
var windowProxy;
var publish = function (activity, onSuccess, onError) {
    if (activity.target) {
        activity.context = {
            "id": target
        };
    } else {
        activity.target = {
            "id": target
        };
    }
    var url = caramel.url('/apis/user-reviews');
    $.ajax({
        url: url,
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(activity),
        success: onSuccess,
        error: onError
    });
    /*$.post(url, {
        activity: JSON.stringify(activity)
    }, onSuccess)*/
};
var showAlert = function (msg) {
    getAlertElement().html(msg).fadeIn("fast");
};
var showLoading = function (status) {
    if (status) {
        getAlertElement().html('').css('display', 'inline-block').addClass('com-alert-wait');
        $loading.fadeIn();
    } else {
        getAlertElement().hide().removeClass('com-alert-wait');
        $loading.fadeOut();
    }
};
$container.on('click', '#btn-post', function (e) {
    e.preventDefault();
    var disabled = $(this).hasClass('disabled');
    if (disabled) {
        showAlert("Rating required");
        return false;
    }
    var rating = $('.user-rating > .selected-rating').data();
    var review = getTextArea().val().trim();
    if (!rating) {
        showAlert("Rating required");
    } else {
        rating = rating.rating;
        var activity = {
            "verb": "post",
            "isMyComment": true,
            "object": {
                "objectType": "review",
                "content": review,
                rating: rating,
                "likes": {
                    "totalItems": 0
                },
                "dislikes": {
                    "totalItems": 0
                }
            }
        };
        $container.find('#btn-post').attr('disabled', 'disabled');
        showLoading(true);
        var pos = target.indexOf(':');
        var aid = target.substring(pos + 1);
        var type = target.substring(0, pos);
        var addAndRenderNew = function (successCallback, onError) {
            $('#newest').addClass('selected');
            publish(activity, function (published) {
                if ($firstReview.length) {
                    $firstReview.hide();
                    $sort.removeClass('com-sort-hidden');
                }
                if (published.success) {
                    showLoading(false);
                    activity.id = published.id;
                    activity.object.id = published.id;
                    //Remove carbon.super tenant domain from username
                    var pieces = user.split(/[\s@]+/);
                    if (pieces[pieces.length - 1] == 'carbon.super') {
                        user = pieces[pieces.length - 2];
                    }
                    activity.actor = {
                        id: user
                    };
                    usingTemplate(function (template) {
                        var newComment = template(activity);
                        getMyReviewElement().html('').html(newComment);
                        successCallback && successCallback();
                    });
                }
            }, onError);
        };
        addAndRenderNew(function () {
            redrawReviews();
        }, function (error) {
            var errorMessage = JSON.parse(error.responseText).error;
            $('#btn-post[disabled]').removeAttr('disabled');
            $('.user-rating > .selected-rating').removeClass('selected-rating');
            notifyError(errorMessage);
        });
    }
});
$stream.on('click', '.icon-thumbs-down', function (e) {
    e.preventDefault();
    var $tDownBtn = $(e.target);
    var $review = $tDownBtn.parents('.com-review');
    var id = $review.attr('data-target-id');
    var $tDownCount = $review.find('.com-dislike-count');
    var activity = {
        target: {
            id: id
        },
        object: {}
    };
    var $opposite = $review.find('.icon-thumbs-up');
    if ($opposite.hasClass('selected')) {
        var ulikeActivity = {
            target: {
                id: id
            },
            object: {}
        };
        var $likeCount = $review.find('.com-like-count');
        ulikeActivity.verb = 'unlike';
        publish(ulikeActivity, function () {
            $likeCount.text((Number($likeCount.text()) - 1) || '');
        });
        $opposite.removeClass('selected');
    }
    if ($tDownBtn.hasClass('selected')) {
        activity.verb = 'undislike';
        publish(activity, function () {
            $tDownCount.text((Number($tDownCount.text()) - 1) || '');
        });
        $tDownBtn.removeClass('selected');
    } else {
        activity.verb = 'dislike';
        publish(activity, function () {
            $tDownCount.text(Number($tDownCount.text()) + 1);
        });
        $tDownBtn.addClass('selected');
    }
});
$stream.on('click', '.icon-thumbs-up', function (e) {
    e.preventDefault();
    var $tUpBtn = $(e.target);
    var $review = $tUpBtn.parents('.com-review');
    var id = $review.attr('data-target-id');
    var $likeCount = $review.find('.com-like-count');
    var activity = {
        target: {
            id: id
        },
        object: {}
    };
    var $opposite = $review.find('.icon-thumbs-down');
    if ($opposite.hasClass('selected')) {
        var uDislikeActivity = {
            target: {
                id: id
            },
            object: {}
        };
        var $uDislikeCount = $review.find('.com-dislike-count');
        uDislikeActivity.verb = 'undislike';
        publish(uDislikeActivity, function () {
            $uDislikeCount.text((Number($uDislikeCount.text()) - 1) || '');
        });
        $opposite.removeClass('selected');
    }
    if ($tUpBtn.hasClass('selected')) {
        activity.verb = 'unlike';
        publish(activity, function () {
            $likeCount.text((Number($likeCount.text()) - 1) || '');
        });
        $tUpBtn.removeClass('selected');
    } else {
        activity.verb = 'like';
        publish(activity, function () {
            $likeCount.text(Number($likeCount.text()) + 1);
        });
        $tUpBtn.addClass('selected');
    }
});
$more.on('click', '.load-more', function (e) {
    e.preventDefault();
    var offset = parseInt($('.load-more').attr("value"));
    var url = caramel.url('/apis/user-reviews');
    $.get(url, {
        target: target,
        sortBy: $('.com-sort .selected').attr('id'),
        offset: offset,
        limit: 10
    }, function (obj) {
        var reviews = obj || [];
        if (jQuery.isEmptyObject(reviews) || reviews.length < 10) {
            $more.hide();
            $empty_list.text("No more activities to retrieve.");
        }
        usingTemplate(function (template) {
            var str = "";
            for (var i = 0; i < reviews.length; i++) {
                var review = reviews[i];
                str += template(review);
            }
            $stream.append(str);
            //callback && callback();
            adjustHeight();
            $('.load-more').attr("value", parseInt(offset) + 10);
        });
    });
});
$stream.on('click', '#btn-delete', function (e) {
    e.preventDefault();
    var $deleteBtn = $(e.target);
    var $review = $deleteBtn.parents('.com-review');
    var id = $review.attr('data-target-id');
    var url = caramel.url('/apis/user-review/' + id);
    $.ajax({
        url: url,
        type: 'DELETE',
        success: function (obj) {
            if (obj.success) {
                $review.remove();
            }
        }
    });
});
$container.on('click', '#btn-delete', function (e) {
    showLoading(true);
    e.preventDefault();
    var $deleteBtn = $(e.target);
    var $review = $deleteBtn.parents('.com-review');
    var id = $review.attr('data-target-id');
    var url = caramel.url('/apis/user-review/' + id);
    $.ajax({
        url: url,
        type: 'DELETE',
        success: function () {
            $('.com-review[data-target-id="' + id + '"]').fadeOut();
            caramel.partials({
                comment: '/extensions/app/social-reviews/themes/' + caramel.themer + '/partials/comment-input.hbs'
            }, function () {
                var template = Handlebars.partials['comment'];
                var commentInput = template({myReview: null, type: target.split(':')[0], ratings: [5, 4, 3, 2, 1]});
                $(".row.com-add").replaceWith(commentInput);
            });
        }
    });
});
$container.on('click', '#btn-update', function (e) {
    showLoading(true);
    e.preventDefault();
    var rating = $('.user-rating > .selected-rating').data().rating;
    var review = getTextArea().val().trim();
    var id = $(this).data('id');
    var url = caramel.url('/apis/user-review/' + id);
    var target = target;
    var data = {
        rating: rating,
        review: review,
        id: id,
        target: target
    };
    $.ajax({
        url: url,
        type: 'PUT',
        contentType: 'application/json',
        data: JSON.stringify(data),
        success: function (response) {
            /*Placeholder for update method*/
            return false;
        }
    });
});
$container.on('click', '#btn-edit', function (e) {
    showLoading(true);
    var myReview = getMyReviewElement();
    var rating = myReview.find('.com-rating').data('rating');
    var review = myReview.find('.com-content').html().trim();
    var id = myReview.find('.com-review').data('target-id');
    var editable = {
        rating: rating,
        review: review,
        id: id
    };
    e.preventDefault();
    $('.com-review[data-target-id="' + id + '"]').fadeOut();
    caramel.partials({
        comment: '/extensions/app/social-reviews/themes/' + caramel.themer + '/partials/comment-input.hbs'
    }, function () {
        var template = Handlebars.partials['comment'];
        var commentInput = template(
            {myReview: null, type: target.split(':')[0], ratings: [5, 4, 3, 2, 1], editable: editable});
        $(".row.com-add").replaceWith(commentInput);
    });
});
$container.on('click', '#btn-cancel', function (e) {
    var id = $(this).data('id');
    var activity = $('.com-review[data-target-id="' + id + '"]');
    activity.show();
    getMyReviewElement().empty();
    getMyReviewElement().append(activity.clone());
});
$container.on('click', '.rating-star', function () {
    getAlertElement().html('').fadeOut("fast");
    $('#btn-post.disabled').removeClass('disabled');
    $(this).siblings().removeClass("selected-rating");
    $(this).addClass("selected-rating");
});
$stream.niceScroll();
<|endoftext|>


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

/**
 * Internal dependencies
 */
import {
	Input,
	TextField,
} from '../../../../material-components';
import classnames from 'classnames';

export default function CreateAccountField( {
	hasError,
	value,
	setValue,
	name,
	label,
} ) {
	if ( 'undefined' === typeof value ) {
		return null;
	}

	return (
		<TextField
			className={ classnames(
				'mdc-text-field',
				{ 'mdc-text-field--error': hasError }
			) }
			label={ label }
			name={ name }
			onChange={ ( event ) => {
				setValue( event.target.value, name );
			} }
			outlined
			required
		>
			<Input
				name={ name }
				value={ value }
			/>
		</TextField>
	);
}
<commit_msg>Improve and document field value check.<commit_after>/**
 * CreateAccountField component.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import {
	Input,
	TextField,
} from '../../../../material-components';
import classnames from 'classnames';

export default function CreateAccountField( {
	hasError,
	value,
	setValue,
	name,
	label,
} ) {
	// Ensure field doesn't render until default value is available, fixing a potential render bug.
	if ( value === undefined ) {
		return null;
	}

	return (
		<TextField
			className={ classnames(
				'mdc-text-field',
				{ 'mdc-text-field--error': hasError }
			) }
			label={ label }
			name={ name }
			onChange={ ( event ) => {
				setValue( event.target.value, name );
			} }
			outlined
			required
		>
			<Input
				name={ name }
				value={ value }
			/>
		</TextField>
	);
}
<|endoftext|>


<commit_before>'use strict';

var instagram = require('../instagram.js');

exports.get = function(req, res) {
	var fromTime;
	if(req.query.fromTime) {
		fromTime = req.query.fromTime;
	}
    instagram.nature(fromTime, function(err, images) {
        if (err) {
            res.status(500);
            res.jsonp({
                error: 'Error while getting data from instagram'
            });
        } else {
            res.jsonp(images);
        }
    });
};
<commit_msg>Changed fromTime to lowercase fromtime<commit_after>'use strict';

var instagram = require('../instagram.js');

exports.get = function(req, res) {
	var fromTime;
	if(req.query.fromTime) {
		fromTime = req.query.fromtime;
	}
    instagram.nature(fromTime, function(err, images) {
        if (err) {
            res.status(500);
            res.jsonp({
                error: 'Error while getting data from instagram'
            });
        } else {
            res.jsonp(images);
        }
    });
};
<|endoftext|>


<commit_before>/*global $:false, app:true, editor:false*/

// 'use strict';

$(document).ready(function() {
	app = {

		// Chrome app variables
		markdownPreviewIframe: $('#preview-iframe'),
		isMarkdownPreviewIframeLoaded: false,
		markdownPreviewIframeLoadEventCallbacks: $.Callbacks(),

		init: function() {
			editor.init();
			this.initBindings();
		},

		initBindings: function() {
			$(window).on('message', function(e) {
				app.receiveMessage(e.originalEvent);
			});

			// In the Chrome app, the preview panel requires to be in a sandboxed iframe, hence isn't loaded immediately with the rest of the document
			this.markdownPreviewIframe.on('load', function() {
				app.isMarkdownPreviewIframeLoaded = true;
				app.markdownPreviewIframeLoadEventCallbacks.fire();
			});
		},

		// Post messages to the iframe
		// Currently only used to transfer HTML from this window to the iframe for display
		postMessage: function(data) {
			this.markdownPreviewIframe[0].contentWindow.postMessage(data, '*');
		},

		// Receive messages sent to this window (from the iframe)
		receiveMessage: function(e) {
			if (e.data.hasOwnProperty('height')) {
				this.updateMarkdownPreviewIframeHeight(e.data.height);
			}
		},

		// Save a key/value pair in chrome.storage (either Markdown text or enabled features)
		save: function(key, value) {
			var items = {};
			items[key] = value;
			chrome.storage.local.set(items);
		},

		// Restore the editor's state from chrome.storage (saved Markdown and enabled features)
		restoreState: function(c) {
			// restoreState needs the preview panel to be loaded: if it isn't loaded when restoreState is called, call restoreState again as soon as it is
			if (!this.isMarkdownPreviewIframeLoaded) {
				this.markdownPreviewIframeLoadEventCallbacks.add(function() {
					app.restoreState(c);
				});
				return;
			}

			chrome.storage.local.get(['markdown', 'isFullscreen'], c);
		},

		// Update the preview panel with new HTML
		updateMarkdownPreview: function(markdown, caretPosition) {
			var request = {
				action: 'updateMarkdownPreview',
				caretPosition: caretPosition,
				markdown: markdown
			}
			this.postMessage(request);
		},

		updateMarkdownPreviewIframeHeight: function(height) {
			this.markdownPreviewIframe.css('height', height);
			editor.markdownPreview.trigger('updated.editor');
		}
	};

	app.init();

});

<commit_msg>Added timeout to reduce the number of requests of update<commit_after>/*global $:false, app:true, editor:false*/

// 'use strict';

$(document).ready(function() {
	app = {

		// Chrome app variables
		markdownPreviewIframe: $('#preview-iframe'),
		isMarkdownPreviewIframeLoaded: false,
		markdownPreviewIframeLoadEventCallbacks: $.Callbacks(),

		init: function() {
			editor.init();
			this.initBindings();
		},

		initBindings: function() {
			$(window).on('message', function(e) {
				app.receiveMessage(e.originalEvent);
			});

			// In the Chrome app, the preview panel requires to be in a sandboxed iframe, hence isn't loaded immediately with the rest of the document
			this.markdownPreviewIframe.on('load', function() {
				app.isMarkdownPreviewIframeLoaded = true;
				app.markdownPreviewIframeLoadEventCallbacks.fire();
			});
		},

		// Post messages to the iframe
		// Currently only used to transfer HTML from this window to the iframe for display
		postMessage: function(data) {
			this.markdownPreviewIframe[0].contentWindow.postMessage(data, '*');
		},

		// Receive messages sent to this window (from the iframe)
		receiveMessage: function(e) {
			if (e.data.hasOwnProperty('height')) {
				this.updateMarkdownPreviewIframeHeight(e.data.height);
			}
		},

		// Save a key/value pair in chrome.storage (either Markdown text or enabled features)
		save: function(key, value) {
			var items = {};
			items[key] = value;
			chrome.storage.local.set(items);
		},

		// Restore the editor's state from chrome.storage (saved Markdown and enabled features)
		restoreState: function(c) {
			// restoreState needs the preview panel to be loaded: if it isn't loaded when restoreState is called, call restoreState again as soon as it is
			if (!this.isMarkdownPreviewIframeLoaded) {
				this.markdownPreviewIframeLoadEventCallbacks.add(function() {
					app.restoreState(c);
				});
				return;
			}

			chrome.storage.local.get(['markdown', 'isFullscreen'], c);
		},

		// A timer is used to avoid a burst of requests
		updateTimeout: null,

		// Update the preview panel with new markdown
		updateMarkdownPreview: function(markdown, caretPosition) {

			// Remove the previous request of update
			if (this.updateTimeout !== null) {
				clearTimeout(this.updateTimeout)
			}
			var request = {
				action: 'updateMarkdownPreview',
				caretPosition: caretPosition,
				markdown: markdown
			}

			// Schedule the next update
			this.updateTimeout = setTimeout(function() {
				app.postMessage(request);
			}, 200);
		},

		updateMarkdownPreviewIframeHeight: function(height) {
			this.markdownPreviewIframe.css('height', height);
			editor.markdownPreview.trigger('updated.editor');
		}
	};

	app.init();

});

<|endoftext|>