<commit_before>import * as d3 from "d3";

import {
  accessor,
  assign,
  configPrep,
  constant,
  elem,
  merge
} from "d3plus-common";

import * as shapes from "d3plus-shape";
import {default as Plot} from "./Plot";

/**
    @class Radar
    @extends Plot
    @desc Creates a radar visualization based on an array of data.
*/
export default class Radar extends Plot {

  /**
      @memberof LinePlot
      @desc Invoked when creating a new class instance, and overrides any default parameters inherited from Plot.
      @private
  */
  constructor() {
    super();
    this._discrete = "x";
    this._factor = 1; // CHECK
    this._legend = false;
    this._levels = 6; // CHECK
    this._shape = constant("Circle");

    this._shapeConfig = assign(this._shapeConfig, {
      Circle: {
        opacity: d => d.__d3plusOpacity__ || 1,
        labelConfig: {
          fontResize: true
        }
      }
    });
  }

  /**
      Extends the draw behavior of the abstract Plot class.
      @private
  */
  _draw(callback) {
    super._draw(callback);

    const height = this._height - this._margin.top - this._margin.bottom,
          width = this._width - this._margin.left - this._margin.right;

    const diameter = Math.min(height, width);
    const transform = `translate(${diameter / 2}, ${diameter / 2})`;

    const maxValue = Math.max(...this._data.map(d => d.value));

    // TO-DO
    const allAxis = this._data.map(d => d.skill);
    const total = allAxis.length;
    const radius = this._factor * (diameter / 2);

    for (let j = 0; j < this._levels; j++) {
      const levelFactor = this._factor * radius * ((j + 1) / this._levels);
      this._shapes.push(
        new shapes.Circle()
        .r(r)
          .select(
            elem("g.d3plus-Radar", {
              parent: this._select,
              enter: {transform},
              update: {transform}
            }).node()
          )
          .config(configPrep.bind(this)(this._shapeConfig, "shape", "Circle"))
          .render()
      );
    }

    this._shapes.push(
      new shapes.Circle()
      .r(r)
        .select(
          elem("g.d3plus-Radar", {
            parent: this._select,
            enter: {transform},
            update: {transform}
          }).node()
        )
        .config(configPrep.bind(this)(this._shapeConfig, "shape", "Circle"))
        .render()
    );

    return this;
  }
}
<commit_msg>adds custom paths to radar<commit_after>import * as d3 from "d3";

import {
  accessor,
  assign,
  configPrep,
  constant,
  elem,
  merge
} from "d3plus-common";

import * as shapes from "d3plus-shape";
import {default as Plot} from "./Plot";

/**
    @class Radar
    @extends Plot
    @desc Creates a radar visualization based on an array of data.
*/
export default class Radar extends Plot {

  /**
      @memberof LinePlot
      @desc Invoked when creating a new class instance, and overrides any default parameters inherited from Plot.
      @private
  */
  constructor() {
    super();
    this._discrete = "x";
    this._factor = 1; // CHECK
    this._legend = false;
    this._levels = 3; // CHECK

    this._shapeConfig = assign(this._shapeConfig, {
      Circle: {
        opacity: d => d.__d3plusOpacity__ || 1,
        labelConfig: {
          fontResize: true
        }
      },
      Area: {
        fill: constant("none"),
        strokeWidth: constant(1)
      },

      Path: {
        fill: constant("red"),
        fillOpacity: constant(0.7)
      }
    });
  }

  /**
      Extends the draw behavior of the abstract Plot class.
      @private
  */
  _draw(callback) {
    super._draw(callback);

    const height = this._height - this._margin.top - this._margin.bottom,
          width = this._width - this._margin.left - this._margin.right;

    const diameter = Math.min(height, width);
    const transform = `translate(${diameter / 2}, ${diameter / 2})`;

    const maxValue = Math.max(...this._data.map(d => d.value));

    const polarAxis = Array.from(new Set(this._data.map((d, i) => this._y(d, i))));
    const spaceAxis = Array.from(new Set(this._data.map((d, i) => this._x(d, i))));

    const totalAxis = polarAxis.length;
    const tau = Math.PI * 2;
    const s = tau / totalAxis;

    // TO-DO
    const radius = this._factor * (diameter / 2);
    const allAxis = this._data.map((d, i) => ({
      __d3plus__: true,
      __d3plusRadius__: this._factor * radius * ((i + 1) / totalAxis),
      data: d,
      i,
      id: i
    }));

    this._shapes.push(
      new shapes.Circle()
        .data(allAxis)
        .r(d => d.__d3plusRadius__)
        .select(
          elem("g.d3plus-Radar-item", {
            parent: this._select,
            enter: {transform},
            update: {transform}
          }).node()
        )
        .config(configPrep.bind(this)(this._shapeConfig, "shape", "Area"))
        .render()
    );

    spaceAxis.forEach(space => {
      console.log(space);
      const elm = this._data.filter((d, i) => this._x(d, i) === space);
      const q = elm.map((d, i) => {
        const angle = tau / totalAxis * i,
              r = d.value / maxValue * radius;
        return {
          angle: tau / totalAxis * i,
          x: r * Math.cos(angle),
          y: r * Math.sin(angle)
        };
      });

      const d = `M ${q[0].x} ${q[0].y} ${q
        .map(i => `L ${i.x} ${i.y}`)
        .join(" ")}`;

      this._shapes.push(
        new shapes.Path()
          .data([0])
          .d(d)
          .select(
            elem(`g.d3plus-Radar-item${space}`, {
              parent: this._select,
              enter: {transform},
              update: {transform}
            }).node()
          )
          .config(configPrep.bind(this)(this._shapeConfig, "shape", "Path"))
          .render()
      );
    });

    return this;
  }
}
<|endoftext|>


<commit_before>/* This code assumes that WeavePath.js has already been loaded. */
/* "use strict"; */

/**
 * Requests that an panel object be created if it doesn't already exist at the current path.
 * @param type The object type
 * @param panelX The session state for the "panelX" property.
 * @param panelY The session state for the "panelY" property.
 * @param panelWidth The session state for the "panelWidth" property.
 * @param panelHeight The session state for the "panelHeight" property.
 * @param usePixelValues (Optional) Set this to true if the panel coordinates are given in pixels. Otherwise, they are treated as percentage values.
 */
weave.WeavePath.prototype.requestPanel = function(type, panelX, panelY, panelWidth, panelHeight, usePixelValues)
{
	this.request(type);

	if (!this.weave.evaluateExpression(this.getPath(), "this is DraggablePanel", null, ['weave.ui.DraggablePanel']))
		this._failMessage('requestPanel', type + " is not a DraggablePanel.", this._path);

	if (!usePixelValues)
	{
		panelX = panelX + '%';
		panelY = panelY + '%';
		panelWidth = panelWidth + '%';
		panelHeight = panelHeight + '%';
	}
    return this.state({
        panelX: panelX,
        panelY: panelY,
        panelWidth: panelWidth,
        panelHeight: panelHeight
    });
};

/**
 * This is a shortcut for pushing the path to a plotter from the current path, which should reference a visualization tool.
 * @param plotterName The name of an existing or new plotter.
 * @param plotterType (Optional) The type of plotter to request if it doesn't exist yet.
 */
weave.WeavePath.prototype.pushPlotter = function(plotterName, plotterType)
{
    var path = this.push('children', 'visualization', 'plotManager', 'plotters', plotterName || 'plot');
    if (plotterType)
        path.request(plotterType);
    return path;
};
<commit_msg>updated doc<commit_after>/* This code assumes that WeavePath.js has already been loaded. */
/* "use strict"; */

/**
 * Requests that an panel object be created if it doesn't already exist at the current path.
 * @param type The type of panel requested.
 * @param x A numeric value for the panel X coordinate.
 * @param y A numeric value for the panel Y coordinate.
 * @param width A numeric value for the panel width.
 * @param height A numeric value for the panel height.
 * @param usePixelValues (Optional) Set this to true if the panel coordinates are given in pixels. Otherwise, they are treated as percentage values.
 */
weave.WeavePath.prototype.requestPanel = function(type, x, y, width, height, usePixelValues)
{
	this.request(type);

	if (!this.weave.evaluateExpression(this.getPath(), "this is DraggablePanel", null, ['weave.ui.DraggablePanel']))
		this._failMessage('requestPanel', type + " is not a DraggablePanel type.", this._path);

	if (!usePixelValues)
	{
		panelX = x + '%';
		panelY = y + '%';
		panelWidth = width + '%';
		panelHeight = height + '%';
	}
    return this.state({
        panelX: x,
        panelY: y,
        panelWidth: width,
        panelHeight: height
    });
};

/**
 * This is a shortcut for pushing the path to a plotter from the current path, which should reference a visualization tool.
 * @param plotterName The name of an existing or new plotter.
 * @param plotterType (Optional) The type of plotter to request if it doesn't exist yet.
 */
weave.WeavePath.prototype.pushPlotter = function(plotterName, plotterType)
{
    var path = this.push('children', 'visualization', 'plotManager', 'plotters', plotterName || 'plot');
    if (plotterType)
        path.request(plotterType);
    return path;
};
<|endoftext|>


<commit_before>/**
 * This module is responsible for generating the HTML page response for
 * the react application middleware.
 */

/* eslint-disable react/no-danger */
/* eslint-disable react/no-array-index-key */

import React, { Children } from 'react';
import PropTypes from 'prop-types';
import serialize from 'serialize-javascript';
import { flushChunkNames } from 'react-universal-component/server';

import HTML from 'components/html';
import config from 'utils/config';
import Analytics from 'utils/analytics';

import getClientBundleEntryAssets from './getClientBundleEntryAssets';
import getChunks from './getChunks';
import getManifest from './getManifest';

import ifElse from '../../../internal/utils/logic/ifElse';
import removeNil from '../../../internal/utils/arrays/removeNil';
import ClientConfig from '../../../config/components/ClientConfig';

function KeyedComponent({ children }) {
  return Children.only(children);
}

const facebookPixel = config('facebookPixel');
const twitterPixel = config('twitterPixel');
const analytics = new Analytics({ facebookPixel, twitterPixel });

// Resolve the assets (js/css) for the client bundle's entry chunk.
const clientEntryAssets = getClientBundleEntryAssets();

const webpackManifest = getManifest();

const isDev = process.env.BUILD_FLAG_IS_DEV === 'true';

function stylesheetTag(stylesheetFilePath) {
  return (
    <link href={stylesheetFilePath} media="screen, projection" rel="stylesheet" type="text/css" />
  );
}

function scriptTag(jsFilePath) {
  return <script type="text/javascript" src={jsFilePath} />;
}

// renames html class from no-js to js
function noJs() {
  return (
    <script
      type="text/javascript"
      dangerouslySetInnerHTML={{ __html: `document.documentElement.className =
       document.documentElement.className.replace('no-js', 'js')` }}
    />
  );
}

function ServerHTML(props) {
  const {
    jobsState,
    routerState,
    helmet,
    addHash,
    reactAppString,
    appState,
  } = props;

  // Creates an inline script definition that is protected by the nonce.
  const inlineScript = body => (
    <script type="text/javascript" dangerouslySetInnerHTML={{ __html: addHash(body) }} />
  );

  const chunkNames = flushChunkNames();

  const {
    cssHashRaw = {},
    scripts,
    stylesheets,
  } = getChunks(chunkNames);

  const headerElements = removeNil([
    noJs(),
    ifElse(facebookPixel)(() => inlineScript(analytics.facebook)),
    ifElse(twitterPixel)(() => inlineScript(analytics.twitter)),
    ...ifElse(helmet)(() => helmet.meta.toComponent(), []),
    ...ifElse(helmet)(() => helmet.title.toComponent(), []),
    ...ifElse(helmet)(() => helmet.base.toComponent(), []),
    ...ifElse(helmet)(() => helmet.link.toComponent(), []),
    ifElse(clientEntryAssets && clientEntryAssets.css)(
      () => stylesheetTag(clientEntryAssets.css),
    ),
    ...ifElse(helmet)(() => helmet.style.toComponent(), []),
    ifElse(webpackManifest)(() => inlineScript(`window.__WEBPACK_MANIFEST__=${serialize(webpackManifest, { isJSON: true })};`)),
    ...ifElse(stylesheets)(() => stylesheets.map(s => stylesheetTag(s)), []),
  ]);

  const bodyElements = removeNil([
    ifElse(facebookPixel)(() => analytics.facebookNoscript),
    // Binds the client configuration object to the window object so
    // that we can safely expose some configuration values to the
    // client bundle that gets executed in the browser.
    <ClientConfig addHash={addHash} />,
    ifElse(jobsState)(() => inlineScript(`window.__JOBS_STATE__=${serialize(jobsState, { isJSON: true })}`)),
    ifElse(routerState)(() => inlineScript(`window.__ROUTER_STATE__=${serialize(routerState, { isJSON: true })}`)),
    ifElse(appState)(() => inlineScript(`window.__APP_STATE__=${serialize(appState, { isJSON: true })}`)),
    // Enable the polyfill io script?
    // This can't be configured within a react-helmet component as we
    // may need the polyfill's before our client JS gets parsed.
    // The gated flag is added for feature detection,
    // preventing wrong feature set in chrome simulator
    ifElse(config('polyfillIO.enabled'))(
      () =>
        scriptTag(`${config('polyfillIO.url')}?features=${config('polyfillIO.features').join(',')}&flags=gated`),
    ),
    // When we are in development mode our development server will
    // generate a vendor DLL in order to dramatically reduce our
    // compilation times.  Therefore we need to inject the path to the
    // vendor dll bundle below.
    ifElse(
      isDev && config('bundles.client.devVendorDLL.enabled'),
    )(() =>
      scriptTag(
        `${config('bundles.client.webPath')}${config(
          'bundles.client.devVendorDLL.name',
        )}.js?t=${Date.now()}`,
      )),
    inlineScript(`window.__CSS_CHUNKS__=${serialize(cssHashRaw)}`),
    ...ifElse(scripts)(() => scripts.map(s => scriptTag(s)), []),
    ifElse(clientEntryAssets && clientEntryAssets.js)(
      () => scriptTag(clientEntryAssets.js),
    ),
    ...ifElse(helmet)(() => helmet.script.toComponent(), []),
  ]);

  return (
    <HTML
      htmlAttributes={ifElse(helmet)(() => helmet.htmlAttributes.toComponent(), null)}
      headerElements={headerElements.map((x, idx) =>
        (
          <KeyedComponent key={idx}>
            {x}
          </KeyedComponent>
        ))}
      bodyElements={bodyElements.map((x, idx) =>
        (
          <KeyedComponent key={idx}>
            {x}
          </KeyedComponent>
        ))}
      appBodyString={reactAppString}
    />
  );
}

ServerHTML.propTypes = {
  jobsState: PropTypes.object,
  routerState: PropTypes.object,
  helmet: PropTypes.object,
  addHash: PropTypes.func,
  reactAppString: PropTypes.string,
  appState: PropTypes.object,
};

export default ServerHTML;
<commit_msg>Moves boolean<commit_after>/**
 * This module is responsible for generating the HTML page response for
 * the react application middleware.
 */

/* eslint-disable react/no-danger */
/* eslint-disable react/no-array-index-key */

import React, { Children } from 'react';
import PropTypes from 'prop-types';
import serialize from 'serialize-javascript';
import { flushChunkNames } from 'react-universal-component/server';

import HTML from 'components/html';
import config from 'utils/config';
import Analytics from 'utils/analytics';

import getClientBundleEntryAssets from './getClientBundleEntryAssets';
import getChunks from './getChunks';
import getManifest from './getManifest';

import ifElse from '../../../internal/utils/logic/ifElse';
import removeNil from '../../../internal/utils/arrays/removeNil';
import ClientConfig from '../../../config/components/ClientConfig';

function KeyedComponent({ children }) {
  return Children.only(children);
}

const facebookPixel = config('facebookPixel');
const twitterPixel = config('twitterPixel');
const analytics = new Analytics({ facebookPixel, twitterPixel });

// Resolve the assets (js/css) for the client bundle's entry chunk.
const clientEntryAssets = getClientBundleEntryAssets();

const webpackManifest = getManifest();

function stylesheetTag(stylesheetFilePath) {
  return (
    <link href={stylesheetFilePath} media="screen, projection" rel="stylesheet" type="text/css" />
  );
}

function scriptTag(jsFilePath) {
  return <script type="text/javascript" src={jsFilePath} />;
}

// renames html class from no-js to js
function noJs() {
  return (
    <script
      type="text/javascript"
      dangerouslySetInnerHTML={{ __html: `document.documentElement.className =
       document.documentElement.className.replace('no-js', 'js')` }}
    />
  );
}

function ServerHTML(props) {
  const {
    jobsState,
    routerState,
    helmet,
    addHash,
    reactAppString,
    appState,
  } = props;

  // Creates an inline script definition that is protected by the nonce.
  const inlineScript = body => (
    <script type="text/javascript" dangerouslySetInnerHTML={{ __html: addHash(body) }} />
  );

  const chunkNames = flushChunkNames();

  const {
    cssHashRaw = {},
    scripts,
    stylesheets,
  } = getChunks(chunkNames);

  const headerElements = removeNil([
    noJs(),
    ifElse(facebookPixel)(() => inlineScript(analytics.facebook)),
    ifElse(twitterPixel)(() => inlineScript(analytics.twitter)),
    ...ifElse(helmet)(() => helmet.meta.toComponent(), []),
    ...ifElse(helmet)(() => helmet.title.toComponent(), []),
    ...ifElse(helmet)(() => helmet.base.toComponent(), []),
    ...ifElse(helmet)(() => helmet.link.toComponent(), []),
    ifElse(clientEntryAssets && clientEntryAssets.css)(
      () => stylesheetTag(clientEntryAssets.css),
    ),
    ...ifElse(helmet)(() => helmet.style.toComponent(), []),
    ifElse(webpackManifest)(() => inlineScript(`window.__WEBPACK_MANIFEST__=${serialize(webpackManifest, { isJSON: true })};`)),
    ...ifElse(stylesheets)(() => stylesheets.map(s => stylesheetTag(s)), []),
  ]);

  const bodyElements = removeNil([
    ifElse(facebookPixel)(() => analytics.facebookNoscript),
    // Binds the client configuration object to the window object so
    // that we can safely expose some configuration values to the
    // client bundle that gets executed in the browser.
    <ClientConfig addHash={addHash} />,
    ifElse(jobsState)(() => inlineScript(`window.__JOBS_STATE__=${serialize(jobsState, { isJSON: true })}`)),
    ifElse(routerState)(() => inlineScript(`window.__ROUTER_STATE__=${serialize(routerState, { isJSON: true })}`)),
    ifElse(appState)(() => inlineScript(`window.__APP_STATE__=${serialize(appState, { isJSON: true })}`)),
    // Enable the polyfill io script?
    // This can't be configured within a react-helmet component as we
    // may need the polyfill's before our client JS gets parsed.
    // The gated flag is added for feature detection,
    // preventing wrong feature set in chrome simulator
    ifElse(config('polyfillIO.enabled'))(
      () =>
        scriptTag(`${config('polyfillIO.url')}?features=${config('polyfillIO.features').join(',')}&flags=gated`),
    ),
    // When we are in development mode our development server will
    // generate a vendor DLL in order to dramatically reduce our
    // compilation times.  Therefore we need to inject the path to the
    // vendor dll bundle below.
    ifElse(
      process.env.BUILD_FLAG_IS_DEV === 'true' && config('bundles.client.devVendorDLL.enabled'),
    )(() =>
      scriptTag(
        `${config('bundles.client.webPath')}${config(
          'bundles.client.devVendorDLL.name',
        )}.js?t=${Date.now()}`,
      )),
    inlineScript(`window.__CSS_CHUNKS__=${serialize(cssHashRaw)}`),
    ...ifElse(scripts)(() => scripts.map(s => scriptTag(s)), []),
    ifElse(clientEntryAssets && clientEntryAssets.js)(
      () => scriptTag(clientEntryAssets.js),
    ),
    ...ifElse(helmet)(() => helmet.script.toComponent(), []),
  ]);

  return (
    <HTML
      htmlAttributes={ifElse(helmet)(() => helmet.htmlAttributes.toComponent(), null)}
      headerElements={headerElements.map((x, idx) =>
        (
          <KeyedComponent key={idx}>
            {x}
          </KeyedComponent>
        ))}
      bodyElements={bodyElements.map((x, idx) =>
        (
          <KeyedComponent key={idx}>
            {x}
          </KeyedComponent>
        ))}
      appBodyString={reactAppString}
    />
  );
}

ServerHTML.propTypes = {
  jobsState: PropTypes.object,
  routerState: PropTypes.object,
  helmet: PropTypes.object,
  addHash: PropTypes.func,
  reactAppString: PropTypes.string,
  appState: PropTypes.object,
};

export default ServerHTML;
<|endoftext|>


<commit_before>/* global describe, it, xit, before, beforeEach, after, afterEach */
/* jslint node: true, esnext: true */

'use strict';

const chai = require('chai'),
  assert = chai.assert,
  expect = chai.expect,
  should = chai.should(),
  endpoint = require('kronos-endpoint'),
  Service = require('../lib/Service'),
  ServiceConfig = require('../lib/ServiceConfig'),
  ServiceLogger = require('../lib/ServiceLogger'),
  ServiceProviderMixin = require('../lib/ServiceProviderMixin');

class ServiceProvider extends ServiceProviderMixin(Service) {}

class ServiceTest extends Service {
  static get name() {
    return "test";
  }
  get type() {
    return ServiceTest.name;
  }

  get autostart() {
    return true;
  }

  configure(config) {
    delete config.name;
    Object.assign(this, config);
    return this.restartIfRunning();
  }
}

describe('service provider', () => {
  const sp = new ServiceProvider([{
    name: 'a'
  }, {
    name: 'test',
    key3: 3
  }]);

  describe('initial setup', () => {
    describe('config service', () => {
      it('present', () => assert.equal(sp.services.config.name, 'config'));
      it('preserved initial config', () => assert.deepEqual(Object.keys(sp.services.config.preservedConfigs), [
        'a', 'test'
      ]));
    });

    it('logger service', () => assert.equal(sp.services.logger.name, 'logger'));
    it('can be started', () => sp.start().then(() => assert.equal(sp.state, 'running')));
    it('service provider service', () => assert.equal(sp.services.a.name, 'a'));
  });

  describe('without initial config', () => {
    const sp = new ServiceProvider();
    it('present', () => assert.equal(sp.services.config.name, 'config'));
  });

  describe('logging', () => {
    // TODO wait until logger service has fullfilled
    sp.info(`logging`);
  });

  describe('command endpoint', () => {
    const testEndpoint = new endpoint.SendEndpoint('test');
    testEndpoint.connected = sp.endpoints.command;

    describe('info', () => {
      it('has response', () =>
        testEndpoint.receive({
          data: {
            action: 'list'
          }
        }).then(r => {
          assert.deepEqual(r.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0), [{
            endpoints: {
              command: { in : true
              },
              log: {
                out: true,
                target: 'logger:log'
              }
            },
            name: 'a',
            type: 'service'
          }, {
            endpoints: {
              config: { in : true
              }
            },
            name: 'config',
            type: 'config'
          }, {
            endpoints: {
              log: { in : true
              }
            },
            name: 'logger',
            type: 'logger'
          }, {
            endpoints: {},
            name: 's2',
            type: 'test'
          }, {
            endpoints: {},
            name: 't2',
            type: 'test'
          }, {
            endpoints: {},
            name: 'test',
            type: 'test'
          }]);
        })
      );
    });
    describe('get', () => {
      it('has response ', () =>
        testEndpoint.receive({
          data: {
            action: 'get',
            service: 'logger',
            options: {
              includeRuntimeInfo: true,
              includeDefaults: true
            }
          }
        }).then(r => {
          assert.deepEqual(r, {
            endpoints: {
              config: { in : true
              },
              log: { in : true
              }
            },
            logLevel: 'info',
            state: 'running',
            name: 'logger',
            type: 'logger'
          });
        })
      );
    });

    describe('start', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: {
            action: 'start',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'running');
        })
      );
    });
    describe('stop', () => {
      it('is stopped', () =>
        testEndpoint.receive({
          data: {
            action: 'stop',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'stopped');
        })
      );
    });

    describe('restart', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: {
            action: 'restart',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'running');
        })
      );
    });

    describe('several restarts', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: [{
            action: 'restart',
            service: 'logger'
          }, {
            action: 'restart',
            service: 'logger'
          }]
        }).then(r => {
          assert.equal(r[1].state, 'running');
        })
      );
    });

    describe('restart unknown service', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: {
            action: 'restart',
            service: 'invalid'
          }
        }).then(r => {
          assert.equal(r.state, 'xxrunning');
        }, e => {
          assert.ok(true);
        })
      );
    });

    describe('unknown command', () => {
      it('rejects', () =>
        testEndpoint.receive({
          data: {
            action: 'unknown',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'xxrunning');
        }, e => {
          assert.ok(true);
        })
      );
    });
  });

  describe('additional service', () => {
    sp.registerService(new ServiceTest({}, sp));
    sp.registerService(new ServiceTest({
      name: "t2"
    }, sp));

    it('test service', () => assert.equal(sp.services.test.name, 'test'));

    describe('configure service', () => {
      it('direct', () => sp.services.test.configure({
        key: 'new value'
      }).then(() =>
        assert.equal(sp.services.test.key, 'new value')
      ));

      it('send change request over config service', () =>
        sp.services.config.endpoints.config.receive([{
          name: 'config'
        }, {
          name: 'unknown'
        }, {
          name: 'test',
          key1: 4711,
          key2: '2'
        }]).then(() =>
          assert.equal(sp.services.test.key1, 4711)
        )
      );
    });

    it('can be unregistered', () =>
      sp.unregisterService('t2').then(s => assert.isUndefined(sp.services.t2))
    );
  });

  describe('declare service', () => {
    describe('with type', () => {
      setTimeout(() =>
        sp.registerServiceFactory(ServiceTest), 50);

      // force pending promises
      sp.declareService({
        name: 's2',
        type: 'test'
      }, true);
      sp.declareService({
        name: 's2',
        type: 'test'
      }, true);
      it('can be declared', () =>
        sp.declareService({
          name: 's2',
          type: 'test',
          key: 1
        }, true).then(
          s => assert.equal(s.name, 's2')
        )
      );

      it('can be declared again', () =>
        sp.declareService({
          name: 's2',
          type: 'test',
          key: 2
        }, true).then(
          s => {
            assert.equal(s.name, 's2');
            assert.equal(s.key, 2);
          }
        )
      );
    });

    describe('without type', () => {
      const sp = new ServiceProvider([{}, {
        name: 'test',
        value: 77
      }]);

      sp.declareService({
        name: 'test'
      }, true);

      setTimeout(() =>
        sp.registerServiceFactory(ServiceTest), 50);

      it('can be declared', () =>
        sp.declareService({
          name: 'test'
        }, true).then(
          s => {
            assert.equal(s.name, 'test');
            //assert.equal(s.value, 77);
          }
        )
      );
    });
  });
});
<commit_msg>test: code cleanup<commit_after>/* global describe, it, xit, before, beforeEach, after, afterEach */
/* jslint node: true, esnext: true */

'use strict';

const chai = require('chai'),
  assert = chai.assert,
  expect = chai.expect,
  should = chai.should(),
  endpoint = require('kronos-endpoint'),
  Service = require('../lib/Service'),
  ServiceConfig = require('../lib/ServiceConfig'),
  ServiceLogger = require('../lib/ServiceLogger'),
  ServiceProviderMixin = require('../lib/ServiceProviderMixin');

class ServiceProvider extends ServiceProviderMixin(Service) {}

class ServiceTest extends Service {
  static get name() {
    return 'test';
  }
  get type() {
    return ServiceTest.name;
  }

  get autostart() {
    return true;
  }

  configure(config) {
    delete config.name;
    Object.assign(this, config);
    return this.restartIfRunning();
  }
}

describe('service provider', () => {
  const sp = new ServiceProvider([{
    name: 'a'
  }, {
    name: 'test',
    key3: 3
  }]);

  describe('initial setup', () => {
    describe('config service', () => {
      it('present', () => assert.equal(sp.services.config.name, 'config'));
      it('preserved initial config', () => assert.deepEqual(Object.keys(sp.services.config.preservedConfigs), [
        'a', 'test'
      ]));
    });

    it('logger service', () => assert.equal(sp.services.logger.name, 'logger'));
    it('can be started', () => sp.start().then(() => assert.equal(sp.state, 'running')));
    it('service provider service', () => assert.equal(sp.services.a.name, 'a'));
  });

  describe('without initial config', () => {
    const sp = new ServiceProvider();
    it('present', () => assert.equal(sp.services.config.name, 'config'));
  });

  describe('logging', () => {
    // TODO wait until logger service has fullfilled
    sp.info(`logging`);
  });

  describe('command endpoint', () => {
    const testEndpoint = new endpoint.SendEndpoint('test');
    testEndpoint.connected = sp.endpoints.command;

    describe('info', () => {
      it('has response', () =>
        testEndpoint.receive({
          data: {
            action: 'list'
          }
        }).then(r => {
          assert.deepEqual(r.sort((a, b) => a.name.localeCompare(b.name)), [{
            endpoints: {
              command: { in : true
              },
              log: {
                out: true,
                target: 'logger:log'
              }
            },
            name: 'a',
            type: 'service'
          }, {
            endpoints: {
              config: { in : true
              }
            },
            name: 'config',
            type: 'config'
          }, {
            endpoints: {
              log: { in : true
              }
            },
            name: 'logger',
            type: 'logger'
          }, {
            endpoints: {},
            name: 's2',
            type: 'test'
          }, {
            endpoints: {},
            name: 't2',
            type: 'test'
          }, {
            endpoints: {},
            name: 'test',
            type: 'test'
          }]);
        })
      );
    });
    describe('get', () => {
      it('has response ', () =>
        testEndpoint.receive({
          data: {
            action: 'get',
            service: 'logger',
            options: {
              includeRuntimeInfo: true,
              includeDefaults: true
            }
          }
        }).then(r => {
          assert.deepEqual(r, {
            endpoints: {
              config: { in : true
              },
              log: { in : true
              }
            },
            logLevel: 'info',
            state: 'running',
            name: 'logger',
            type: 'logger'
          });
        })
      );
    });

    describe('start', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: {
            action: 'start',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'running');
        })
      );
    });
    describe('stop', () => {
      it('is stopped', () =>
        testEndpoint.receive({
          data: {
            action: 'stop',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'stopped');
        })
      );
    });

    describe('restart', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: {
            action: 'restart',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'running');
        })
      );
    });

    describe('several restarts', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: [{
            action: 'restart',
            service: 'logger'
          }, {
            action: 'restart',
            service: 'logger'
          }]
        }).then(r => {
          assert.equal(r[1].state, 'running');
        })
      );
    });

    describe('restart unknown service', () => {
      it('is running', () =>
        testEndpoint.receive({
          data: {
            action: 'restart',
            service: 'invalid'
          }
        }).then(r => {
          assert.equal(r.state, 'xxrunning');
        }, e => {
          assert.ok(true);
        })
      );
    });

    describe('unknown command', () => {
      it('rejects', () =>
        testEndpoint.receive({
          data: {
            action: 'unknown',
            service: 'logger'
          }
        }).then(r => {
          assert.equal(r.state, 'xxrunning');
        }, e => {
          assert.ok(true);
        })
      );
    });
  });

  describe('additional service', () => {
    sp.registerService(new ServiceTest({}, sp));
    sp.registerService(new ServiceTest({
      name: "t2"
    }, sp));

    it('test service', () => assert.equal(sp.services.test.name, 'test'));

    describe('configure service', () => {
      it('direct', () => sp.services.test.configure({
        key: 'new value'
      }).then(() =>
        assert.equal(sp.services.test.key, 'new value')
      ));

      it('send change request over config service', () =>
        sp.services.config.endpoints.config.receive([{
          name: 'config'
        }, {
          name: 'unknown'
        }, {
          name: 'test',
          key1: 4711,
          key2: '2'
        }]).then(() =>
          assert.equal(sp.services.test.key1, 4711)
        )
      );
    });

    it('can be unregistered', () =>
      sp.unregisterService('t2').then(s => assert.isUndefined(sp.services.t2))
    );
  });

  describe('declare service', () => {
    describe('with type', () => {
      setTimeout(() =>
        sp.registerServiceFactory(ServiceTest), 50);

      // force pending promises
      sp.declareService({
        name: 's2',
        type: 'test'
      }, true);
      sp.declareService({
        name: 's2',
        type: 'test'
      }, true);
      it('can be declared', () =>
        sp.declareService({
          name: 's2',
          type: 'test',
          key: 1
        }, true).then(
          s => assert.equal(s.name, 's2')
        )
      );

      it('can be declared again', () =>
        sp.declareService({
          name: 's2',
          type: 'test',
          key: 2
        }, true).then(
          s => {
            assert.equal(s.name, 's2');
            assert.equal(s.key, 2);
          }
        )
      );
    });

    describe('without type', () => {
      const sp = new ServiceProvider([{}, {
        name: 'test',
        value: 77
      }]);

      sp.declareService({
        name: 'test'
      }, true);

      setTimeout(() =>
        sp.registerServiceFactory(ServiceTest), 50);

      it('can be declared', () =>
        sp.declareService({
          name: 'test'
        }, true).then(
          s => {
            assert.equal(s.name, 'test');
            //assert.equal(s.value, 77);
          }
        )
      );
    });
  });
});
<|endoftext|>


<commit_before>// Used by extensions that call method by name or by itself on resolved object

'use strict';

var isArray    = Array.isArray
  , slice      = Array.prototype.slice
  , some       = Array.prototype.some
  , isCallable = require('es5-ext/lib/Object/is-callable')
  , deferred   = require('../../../deferred')
  , promise    = require('../../../promise')
  , isPromise  = require('../../../is-promise');

module.exports = function (base, fn, args, apply, resolve, async) {
	var d, result;
	if (base.failed) {
		return resolve(base.promise);
	}
	if (!isCallable(fn)) {
		if (!isCallable(base.value[fn])) {
			return resolve(new Error("Cannot invoke '" + fn +
				"' on given value. It's not a function."));
		}
		fn = base.value[fn];
	}
	if (some.call(args, isPromise)) {
		if (resolve === promise) {
			d = deferred();
			resolve = d.resolve;
		}
		deferred.apply(null, args)(function (args) {
			apply.call(base.value, fn, isArray(args) ? args : [args], resolve);
		});
	} else {
		if (async && (resolve === promise)) {
			d = deferred();
			resolve = d.resolve;
		}
		result = apply.call(base.value, fn, args, resolve);
		if (!async) {
			return result;
		}
	}
	return d && d.promise;
};
<commit_msg>Fixed error handling in invoke extension for case in which context object is null<commit_after>// Used by extensions that call method by name or by itself on resolved object

'use strict';

var isArray    = Array.isArray
  , slice      = Array.prototype.slice
  , some       = Array.prototype.some
  , isCallable = require('es5-ext/lib/Object/is-callable')
  , deferred   = require('../../../deferred')
  , promise    = require('../../../promise')
  , isPromise  = require('../../../is-promise');

module.exports = function (base, fn, args, apply, resolve, async) {
	var d, result;
	if (base.failed) {
		return resolve(base.promise);
	}
	if (!isCallable(fn)) {
		if (!base.value || !isCallable(base.value[fn])) {
			return resolve(new Error("Cannot invoke '" + fn +
				"' on given value. It's not a function."));
		}
		fn = base.value[fn];
	}
	if (some.call(args, isPromise)) {
		if (resolve === promise) {
			d = deferred();
			resolve = d.resolve;
		}
		deferred.apply(null, args)(function (args) {
			apply.call(base.value, fn, isArray(args) ? args : [args], resolve);
		});
	} else {
		if (async && (resolve === promise)) {
			d = deferred();
			resolve = d.resolve;
		}
		result = apply.call(base.value, fn, args, resolve);
		if (!async) {
			return result;
		}
	}
	return d && d.promise;
};
<|endoftext|>


<commit_before>/*!
	Copyright (C) 2016 Matthew D. Mower

	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

		 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 definitions = {
    findDoi: /\b(10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])\S)+)\b/ig,
    findUrl: /^(?:https?\:\/\/)(?:dx\.)?doi\.org\/(10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])\S)+)$/ig
};

setDefinitions()
.then(replaceDOIsWithLinks)
.catch((error) => {
	console.log("DOI autolink could not run; message: " + error);
});

function setDefinitions() {
	return new Promise((resolve, reject) => {

		chrome.runtime.sendMessage({ cmd: "autolink_vars" }, function (response) {
			if (!response) {
				return reject("Invalid response when fetching definitions");
			}

			var requiredDefinitions = [
				"autolinkRewrite",
				"doiResolver"
			];

			for (var i = 0; i < requiredDefinitions.length; i++) {
				if (response[requiredDefinitions[i]] === undefined) {
					return reject("Missing required definition: " + requiredDefinitions[i]);
				}
				definitions[requiredDefinitions[i]] = response[requiredDefinitions[i]];
			}

			resolve();
		});

	});
}

// https://stackoverflow.com/questions/1444409/in-javascript-how-can-i-replace-text-in-an-html-page-without-affecting-the-tags
function replaceDOIsWithLinks() {
	replaceInElement(document.body, definitions.findDoi, function(match) {
		var link = document.createElement('a');
		link.href = definitions.doiResolver + match[0];
		link.appendChild(document.createTextNode(match[0]));
		return link;
	});
}

// iterate over child nodes in reverse, as replacement may increase length of child node list.
function replaceInElement(element, find, replace) {
	// don't touch these elements
	var forbiddenTags = ["a", "input", "script", "style", "textarea"];
	for (var i = element.childNodes.length - 1; i >= 0; i--) {
		var child = element.childNodes[i];
		if (child.nodeType === Node.ELEMENT_NODE) {
			if (forbiddenTags.indexOf(child.nodeName.toLowerCase()) < 0) {
				replaceInElement(child, find, replace);
			} else if (definitions.autolinkRewrite && child.nodeName.toLowerCase() == "a") {
				if (definitions.findUrl.test(child.href)) {
					child.href = child.href.replace(definitions.findUrl, definitions.doiResolver + "$1");
				}
			}
		} else if (child.nodeType === Node.TEXT_NODE) {
			replaceInText(child, find, replace);
		}
	}
}

function replaceInText(text, find, replace) {
	var matches = [];
	var match = find.exec(text.data);
	while (match !== null) {
		matches.push(match);
		match = find.exec(text.data);
	}
	for (var i = matches.length - 1; i >= 0; i--) {
		match = matches[i];
		text.splitText(match.index);
		text.nextSibling.splitText(match[0].length);
		text.parentNode.replaceChild(replace(match), text.nextSibling);
	}
}
<commit_msg>Autolink: Try/Catch main routine<commit_after>/*!
	Copyright (C) 2016 Matthew D. Mower

	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

		 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 definitions = {
    findDoi: /\b(10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])\S)+)\b/ig,
    findUrl: /^(?:https?\:\/\/)(?:dx\.)?doi\.org\/(10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])\S)+)$/ig
};

setDefinitions()
.then(replaceDOIsWithLinks)
.catch((error) => {
	console.log("DOI autolink could not run; message: " + error);
});

function setDefinitions() {
	return new Promise((resolve, reject) => {

		chrome.runtime.sendMessage({ cmd: "autolink_vars" }, function (response) {
			if (!response) {
				return reject("Invalid response when fetching definitions");
			}

			var requiredDefinitions = [
				"autolinkRewrite",
				"doiResolver"
			];

			for (var i = 0; i < requiredDefinitions.length; i++) {
				if (response[requiredDefinitions[i]] === undefined) {
					return reject("Missing required definition: " + requiredDefinitions[i]);
				}
				definitions[requiredDefinitions[i]] = response[requiredDefinitions[i]];
			}

			resolve();
		});

	});
}

// https://stackoverflow.com/questions/1444409/in-javascript-how-can-i-replace-text-in-an-html-page-without-affecting-the-tags
function replaceDOIsWithLinks() {
	try {
		replaceInElement(document.body, definitions.findDoi, function(match) {
			var link = document.createElement('a');
			link.href = definitions.doiResolver + match[0];
			link.appendChild(document.createTextNode(match[0]));
			return link;
		});
	} catch (ex) {
		console.log("DOI autolink encountered an exception", ex);
	}
}

// iterate over child nodes in reverse, as replacement may increase length of child node list.
function replaceInElement(element, find, replace) {
	// don't touch these elements
	var forbiddenTags = ["a", "input", "script", "style", "textarea"];
	for (var i = element.childNodes.length - 1; i >= 0; i--) {
		var child = element.childNodes[i];
		if (child.nodeType === Node.ELEMENT_NODE) {
			if (forbiddenTags.indexOf(child.nodeName.toLowerCase()) < 0) {
				replaceInElement(child, find, replace);
			} else if (definitions.autolinkRewrite && child.nodeName.toLowerCase() == "a") {
				if (definitions.findUrl.test(child.href)) {
					child.href = child.href.replace(definitions.findUrl, definitions.doiResolver + "$1");
				}
			}
		} else if (child.nodeType === Node.TEXT_NODE) {
			replaceInText(child, find, replace);
		}
	}
}

function replaceInText(text, find, replace) {
	var matches = [];
	var match = find.exec(text.data);
	while (match !== null) {
		matches.push(match);
		match = find.exec(text.data);
	}
	for (var i = matches.length - 1; i >= 0; i--) {
		match = matches[i];
		text.splitText(match.index);
		text.nextSibling.splitText(match[0].length);
		text.parentNode.replaceChild(replace(match), text.nextSibling);
	}
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import $ from '../js/jquery.min.js';
import slider from '../js/slider.jquery.js';

//dirty hack around namespacing problem
slider($);

class App extends Component {
  render() {
    return (

        <Navbar schedule={this.props.schedule}/>
        <ShowView schedule={this.props.schedule}/>

    );
  }
}

// Header on top
class Navbar extends Component {
  render() {
    return (

             ShowMaster {this.props.schedule.format}

    );
  }
}

// Main view
class ShowView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      active_scene: 0,
      next_programs: this.props.schedule.schedule[0].programs,
      current_programs: []
    };

    this.handleSceneChange = this.handleSceneChange.bind(this);
    this.handleNextScene= this.handleNextScene.bind(this)
  }

  handleNextScene() {
    if (this.state.active_scene >= this.props.schedule.schedule.length) {
      console.log("End of schedule")
      return ;
    }
    this.setState({
      current_programs: this.state.next_programs
    })
    this.handleSceneChange(this.state.active_scene + 1)

  }

  handleSceneChange(active_scene) {
    active_scene = parseInt(active_scene);

    var programs = this.props.schedule.schedule[active_scene].programs
    this.setState({
      active_scene: active_scene,
      next_programs: programs
    });
  }

  render() {
    return (

            <ProgramView
              active={this.state.active_scene}
              scenes={this.props.schedule.schedule}
              onSceneChange={this.handleSceneChange}

            />

         <QuickProgramPicker
            groups={this.props.schedule.groups}
            programs={this.props.schedule.programs}
            />

          <SceneView
            programs={this.state.next_programs}
            scene_lookup="next"
            onNextScene={this.handleNextScene}/>

          <SceneView
            programs={this.state.current_programs}/>

          <GlobalControls/>

    )
  }
}

// List entry for ProgramView
class ProgramSceneView extends Component {
  onSceneChange() {
    this.props.onSceneChange(this.props.sceneKey);
  }

  render() {
    return (

{this.props.name}

{this.props.desc}

    )
  }
}

// Shows a  list of all scenes
class ProgramView extends Component {
  render() {
    var scenes = []

    for(var key in this.props.scenes) {
      var scene = this.props.scenes[key];
      var active = (this.props.active == key)? "active": "";
      scenes.push(
        <ProgramSceneView
           active={active}
           name={scene.name}
           desc={scene.desc}
           sceneKey={key}
           key={key}
           onSceneChange={this.props.onSceneChange}
          />
      )
    }
    return (

        {scenes}

    );
  }
}

// Entry for QuickProgramPicker
class QuickProgram extends Component {
  render() {
    return (
      {this.props.name}
    );
  }
}

//Shows all groups and programs, allows user to quickly add them to either
// next scene or current scene
class QuickProgramPicker extends Component {
  render() {
    var programs = []
    for (var program_name in this.props.programs){
      programs.push(<QuickProgram key={program_name} name={program_name} color='danger'/>)
    };
    for (var program_name in this.props.groups){
      programs.push(<QuickProgram key={program_name} name={program_name} color='success'/>)
    };

    return (

Quick Programs

        {programs}

    );
  }
}

class SceneViewItem extends Component {
  render() {
    return (

{this.props.name}

          <IntensitySlider value={this.props.intensity}/>

    )
  }
}
// Shows a list of programs in a scene
class SceneView extends Component {
  render() {
    var header;
    var programs=[]
    if (this.props.scene_lookup === "next") {
      header =  (

Next scene <GoButton onNextScene={this.props.onNextScene}/>

      );
    }else {
      header = (

Current Scene

      );
    }
    for (var key in this.props.programs) {
      var intensity = this.props.programs[key]
      programs.push(
        <SceneViewItem name={key} key={key} intensity={intensity}/>
      )
    }
    return (

        {header}
        {programs}

    );
  }
}

class IntensitySlider extends Component {
  componentDidMount() {
    this.slider = $(this.refs.intensitySlider).freshslider({
       step: 1,
       max: 255,
       value: this.props.value
    });
  }

  componentDidUpdate(prevProps, prevState) {
    this.slider.setValue(this.props.value);
  }

  render() {
    return (

    );
  }
}

// Shows Beat button, Panic buttons
class GlobalControls extends Component {
  render() {
    return (

    );
  }
}

class GoButton extends Component {
  render() {
    return (

          <button onClick={this.props.onNextScene} id="button-go" type="button" className="btn btn-success" aria-label="Left Align">
            GO >>
          </button>

    )
  }
}
export default App;

<commit_msg>intensity slider reverse dataflow<commit_after>import React, { Component } from 'react';
import $ from '../js/jquery.min.js';
import slider from '../js/slider.jquery.js';

//dirty hack around namespacing problem
slider($);

class App extends Component {
  render() {
    return (

        <Navbar schedule={this.props.schedule}/>
        <ShowView schedule={this.props.schedule}/>

    );
  }
}

// Header on top
class Navbar extends Component {
  render() {
    return (

             ShowMaster {this.props.schedule.format}

    );
  }
}

// Main view
class ShowView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      active_scene: 0,
      next_programs: $.extend({}, this.props.schedule.schedule[0].programs),
      current_programs: []
    };

    this.handleSceneChange = this.handleSceneChange.bind(this);
    this.handleNextScene= this.handleNextScene.bind(this)
  }

  handleNextScene() {
    if (this.state.active_scene >= this.props.schedule.schedule.length) {
      console.log("End of schedule")
      return ;
    }
    this.setState({
      current_programs: this.state.next_programs
    })
    this.handleSceneChange(this.state.active_scene + 1)

  }

  handleSceneChange(active_scene) {
    active_scene = parseInt(active_scene);

    var programs = this.props.schedule.schedule[active_scene].programs
    this.setState({
      active_scene: active_scene,
      next_programs: $.extend({}, programs)// shallow clone
    });
  }

  onCurrentSceneIntensity(program, intensity) {
    this.state.current_programs[program] = intensity
  }

  onNextSceneIntensity(program, intensity) {
    this.state.next_programs[program] = intensity
  }
  render() {
    return (

            <ProgramView
              active={this.state.active_scene}
              scenes={this.props.schedule.schedule}
              onSceneChange={this.handleSceneChange}

            />

         <QuickProgramPicker
            groups={this.props.schedule.groups}
            programs={this.props.schedule.programs}
            />

          <SceneView
            programs={this.state.next_programs}
            scene_lookup="next"
            onNextScene={this.handleNextScene}
            onIntensityChange={this.onNextSceneIntensity.bind(this)}/>

          <SceneView
            programs={this.state.current_programs}
            onIntensityChange={this.onCurrentSceneIntensity.bind(this)}/>

          <GlobalControls/>

    )
  }
}

// List entry for ProgramView
class ProgramSceneView extends Component {
  onSceneChange() {
    this.props.onSceneChange(this.props.sceneKey);
  }

  render() {
    return (

{this.props.name}

{this.props.desc}

    )
  }
}

// Shows a  list of all scenes
class ProgramView extends Component {
  render() {
    var scenes = []

    for(var key in this.props.scenes) {
      var scene = this.props.scenes[key];
      var active = (this.props.active == key)? "active": "";
      scenes.push(
        <ProgramSceneView
           active={active}
           name={scene.name}
           desc={scene.desc}
           sceneKey={key}
           key={key}
           onSceneChange={this.props.onSceneChange}
          />
      )
    }
    return (

        {scenes}

    );
  }
}

// Entry for QuickProgramPicker
class QuickProgram extends Component {
  render() {
    return (
      {this.props.name}
    );
  }
}

//Shows all groups and programs, allows user to quickly add them to either
// next scene or current scene
class QuickProgramPicker extends Component {
  render() {
    var programs = []
    for (var program_name in this.props.programs){
      programs.push(<QuickProgram key={program_name} name={program_name} color='danger'/>)
    };
    for (var program_name in this.props.groups){
      programs.push(<QuickProgram key={program_name} name={program_name} color='success'/>)
    };

    return (

Quick Programs

        {programs}

    );
  }
}

class SceneViewItem extends Component {
  render() {
    return (

{this.props.name}

          <IntensitySlider onChange={this.props.onIntensityChange.bind(this, this.props.name)} value={this.props.intensity}/>

    )
  }
}
// Shows a list of programs in a scene
class SceneView extends Component {
  render() {
    var header;
    var programs=[]
    if (this.props.scene_lookup === "next") {
      header =  (

Next scene <GoButton onNextScene={this.props.onNextScene}/>

      );
    }else {
      header = (

Current Scene

      );
    }
    for (var key in this.props.programs) {
      var intensity = this.props.programs[key]
      programs.push(
        <SceneViewItem onIntensityChange={this.props.onIntensityChange} name={key} key={key} intensity={intensity}/>
      )
    }
    return (

        {header}
        {programs}

    );
  }
}

class IntensitySlider extends Component {
  componentDidMount() {
    this.slider = $(this.refs.intensitySlider).freshslider({
       step: 1,
       max: 255,
       value: this.props.value,
       onchange: this.props.onChange
    });
  }

  componentDidUpdate(prevProps, prevState) {
    this.slider.setValue(this.props.value);
  }

  render() {
    return (

    );
  }
}

// Shows Beat button, Panic buttons
class GlobalControls extends Component {
  render() {
    return (

    );
  }
}

class GoButton extends Component {
  render() {
    return (

          <button onClick={this.props.onNextScene} id="button-go" type="button" className="btn btn-success" aria-label="Left Align">
            GO >>
          </button>

    )
  }
}
export default App;

<|endoftext|>


<commit_before>// Creates new password reset token and send it to user's email.

'use strict';

var recaptcha = require('nodeca.core/lib/recaptcha');

module.exports = function (N, apiPath) {
  N.validate(apiPath, {
    email:                     { type: 'string', required: true },
    'g-recaptcha-response':    { type: 'string', required: true }
  });

  //
  // Don't limit logged-in users to change pass. Because
  // user can forget password, but still have cookies to remember it.
  //

  // check captcha
  //
  N.wire.before(apiPath, function verify_captcha(env, callback) {
    var privateKey = N.config.options.recaptcha.private_key,
        clientIp   = env.req.ip,
        response   = env.params['g-recaptcha-response'];

    if (!N.config.options.recaptcha) {
      callback();
      return;
    }

    recaptcha.verify(privateKey, clientIp, response, function (err, valid) {
      if (err) {
        callback(new Error('Captcha service error'));
        return;
      }

      if (!valid) {
        callback({
          code:    N.io.CLIENT_ERROR,
          message: env.t('err_captcha_wrong')
        });
        return;
      }

      callback();
    });
  });

  // Search auth record
  //
  N.wire.before(apiPath, function fetch_auth_link(env, callback) {

    N.models.users.AuthLink
        .findOne({ email: env.params.email, type: 'plain', exists: true })
        .lean(true)
        .exec(function (err, authlink) {

      if (err) {
        callback(err);
        return;
      }

      if (!authlink) {
        callback({
          code:    N.io.CLIENT_ERROR,
          message: env.t('err_email_unknown')
        });
        return;
      }

      env.data.authlink = authlink;

      callback();
    });
  });

  // Create token & send email
  //
  N.wire.on(apiPath, function create_reset_confirmation(env, callback) {
    var authlink = env.data.authlink;

    N.models.users.TokenResetPassword.create({
      authlink_id: authlink._id,
      ip:          env.req.ip
    }, function (err, token) {

      if (err) {
        callback(err);
        return;
      }

      N.settings.get('general_project_name', function (err, general_project_name) {
        if (err) {
          callback(err);
          return;
        }

        var link = env.helpers.url_to('users.auth.reset_password.change_show', {
          secret_key: token.secret_key
        });

        N.mailer.send({
          to:      authlink.email,
          subject: env.t('email_subject', { project_name: general_project_name }),
          text:    env.t('email_text',    { link: link })
        }, callback);
      });
    });
  });
};
<commit_msg>Fixed recaptcha check on password reset<commit_after>// Creates new password reset token and send it to user's email.

'use strict';

var recaptcha = require('nodeca.core/lib/recaptcha');

module.exports = function (N, apiPath) {
  N.validate(apiPath, {
    email:                     { type: 'string', required: true },
    'g-recaptcha-response':    { type: 'string', required: false }
  });

  //
  // Don't limit logged-in users to change pass. Because
  // user can forget password, but still have cookies to remember it.
  //

  // check captcha
  //
  N.wire.before(apiPath, function verify_captcha(env, callback) {
    if (!N.config.options.recaptcha) {
      callback();
      return;
    }

    var privateKey = N.config.options.recaptcha.private_key,
        clientIp   = env.req.ip,
        response   = env.params['g-recaptcha-response'];

    if (!N.config.options.recaptcha) {
      callback();
      return;
    }

    recaptcha.verify(privateKey, clientIp, response, function (err, valid) {
      if (err) {
        callback(new Error('Captcha service error'));
        return;
      }

      if (!valid) {
        callback({
          code:    N.io.CLIENT_ERROR,
          message: env.t('err_captcha_wrong')
        });
        return;
      }

      callback();
    });
  });

  // Search auth record
  //
  N.wire.before(apiPath, function fetch_auth_link(env, callback) {

    N.models.users.AuthLink
        .findOne({ email: env.params.email, type: 'plain', exists: true })
        .lean(true)
        .exec(function (err, authlink) {

      if (err) {
        callback(err);
        return;
      }

      if (!authlink) {
        callback({
          code:    N.io.CLIENT_ERROR,
          message: env.t('err_email_unknown')
        });
        return;
      }

      env.data.authlink = authlink;

      callback();
    });
  });

  // Create token & send email
  //
  N.wire.on(apiPath, function create_reset_confirmation(env, callback) {
    var authlink = env.data.authlink;

    N.models.users.TokenResetPassword.create({
      authlink_id: authlink._id,
      ip:          env.req.ip
    }, function (err, token) {

      if (err) {
        callback(err);
        return;
      }

      N.settings.get('general_project_name', function (err, general_project_name) {
        if (err) {
          callback(err);
          return;
        }

        var link = env.helpers.url_to('users.auth.reset_password.change_show', {
          secret_key: token.secret_key
        });

        N.mailer.send({
          to:      authlink.email,
          subject: env.t('email_subject', { project_name: general_project_name }),
          text:    env.t('email_text',    { link: link })
        }, callback);
      });
    });
  });
};
<|endoftext|>


<commit_before>// @flow

const { logger } = require('@lagoon/commons/src/local-logging');

const { getRocketChatInfoForProject } = require('@lagoon/commons/src/api');

const { URL } = require('url');
const http = require('https');

export type ChannelWrapper = {
  ack: (msg: Object) => void,
}

export type RabbitMQMsg = {
  content: Buffer,
  fields: Object,
  properties: Object,
};

export type Project = {
  rocketchat: Object,
  name: string,
};

async function readFromRabbitMQ (msg: RabbitMQMsg, channelWrapperLogs: ChannelWrapper): Promise<void> {
  const {
    content,
    fields,
    properties,
  } = msg;

  const logMessage = JSON.parse(content.toString())

  const {
    severity,
    project,
    uuid,
    event,
    meta,
    message
  } = logMessage

  const appId = msg.properties.appId || ""

 logger.verbose(`received ${event}`, logMessage)

  var text

  switch (event) {

    case "github:pull_request:closed:handled":
    case "github:pull_request:opened:handled":
    case "github:pull_request:synchronize:handled":
    case "bitbucket:pullrequest:created:handled":
    case "bitbucket:pullrequest:updated:handled":
    case "bitbucket:pullrequest:fulfilled:handled":
    case "bitbucket:pullrequest:rejected:handled":
      sendToRocketChat(project, message, '#E8E8E8', ':information_source:', channelWrapperLogs, msg, appId)
      break;
    case "github:delete:handled":
    case "github:push:handled":
    case "bitbucket:repo:push:handled":
    case "gitlab:push:handled":
      console.log(`tyler: ${JSON.stringify(meta)}`);
      text = `*[${meta.projectName}]* [${meta.branchName}](${meta.repoUrl}/tree/${meta.branchName})`
      if (meta.shortSha){
        text = `${text} ([${meta.shortSha}](${meta.commitUrl}))`
      }
      text = `${text} pushed in [${meta.pathWithNamespace}](${meta.repoUrl})`
      sendToRocketChat(project, text, '#E8E8E8', ':information_source:', channelWrapperLogs, msg, appId)
      break;

    case "rest:deploy:receive":
    case "rest:remove:receive":
    case "rest:promote:receive":
      sendToRocketChat(project, message, '#E8E8E8', ':information_source:', channelWrapperLogs, msg, appId)
      break;

    case "task:deploy-openshift:finished":
    case "task:remove-openshift:finished":
    case "task:remove-openshift-resources:finished":
    case "task:builddeploy-openshift:complete":
      text = `*[${meta.projectName}]* `
      if (meta.shortSha) {
        text = `${text} \`${meta.branchName}\` (${meta.shortSha})`
      } else {
        text = `${text} \`${meta.branchName}\``
      }
      text = `${text} Build \`${meta.buildName}\` complete. ${meta.logLink} \n ${meta.route}\n ${meta.routes.join("\n")}`
      sendToRocketChat(project, text, 'lawngreen', ':white_check_mark:', channelWrapperLogs, msg, appId)
      break;

    case "task:deploy-openshift:retry":
    case "task:remove-openshift:retry":
    case "task:remove-openshift-resources:retry":
      sendToRocketChat(project, message, 'gold', ':warning:', channelWrapperLogs, msg, appId)
      break;

    case "task:deploy-openshift:error":
    case "task:remove-openshift:error":
    case "task:remove-openshift-resources:error":
    case "task:builddeploy-openshift:failed":
      sendToRocketChat(project, message, 'red', ':bangbang:', channelWrapperLogs, msg, appId)
      break;

    case "github:pull_request:closed:CannotDeleteProductionEnvironment":
    case "github:push:CannotDeleteProductionEnvironment":
    case "bitbucket:repo:push:CannotDeleteProductionEnvironment":
    case "gitlab:push:CannotDeleteProductionEnvironment":
    case "rest:remove:CannotDeleteProductionEnvironment":
      sendToRocketChat(project, message, 'gold', ':warning:', channelWrapperLogs, msg, appId)
      break;

    case "unresolvedProject:webhooks2tasks":
    case "unhandledWebhook":
    case "webhooks:receive":
    case "task:deploy-openshift:start":
    case "task:remove-openshift:start":
    case "task:remove-openshift-resources:start":
    case "task:builddeploy-openshift:running":
      // known logs entries that should never go to RocketChat
      channelWrapperLogs.ack(msg)
      break;

    default:
      logger.info(`unhandled log message ${event} ${JSON.stringify(logMessage)}`)
      return channelWrapperLogs.ack(msg)
  }

}

const sendToRocketChat = async (project, message, color, emoji, channelWrapperLogs, msg, appId) => {
  let projectRocketChats;
  try {
    projectRocketChats = await getRocketChatInfoForProject(project)
  }
  catch (error) {
    logger.error(`No RocketChat information found, error: ${error}`)
    return channelWrapperLogs.ack(msg)
  }
  projectRocketChats.forEach(async (projectRocketChat) => {
    const { channel, webhook } = projectRocketChat;
    const rocketchat = new URL(webhook);

    var data = JSON.stringify({
      channel: `#${channel}`,
      attachments: [{
        text: `${emoji} ${message}`,
        color: color,
      }]
    });

    var options = {
      hostname: rocketchat.hostname,
      port: rocketchat.port,
      path: rocketchat.pathname,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': data.length
      }
    };

    var req = http.request(options, function(res) {
      res.setEncoding('utf8');
    });

    req.on('error', function(e) {
      logger.error(`problem with request: ${e.message}`);
    });
    req.write(data);
    req.end();
  });
  channelWrapperLogs.ack(msg)
  return
}

module.exports = readFromRabbitMQ;
<commit_msg>#700 - add source to RC message<commit_after>// @flow

const { logger } = require('@lagoon/commons/src/local-logging');

const { getRocketChatInfoForProject } = require('@lagoon/commons/src/api');

const { URL } = require('url');
const http = require('https');

export type ChannelWrapper = {
  ack: (msg: Object) => void,
}

export type RabbitMQMsg = {
  content: Buffer,
  fields: Object,
  properties: Object,
};

export type Project = {
  rocketchat: Object,
  name: string,
};

async function readFromRabbitMQ (msg: RabbitMQMsg, channelWrapperLogs: ChannelWrapper): Promise<void> {
  const {
    content,
    fields,
    properties,
  } = msg;

  const logMessage = JSON.parse(content.toString())

  const {
    severity,
    project,
    uuid,
    event,
    meta,
    message
  } = logMessage

  const appId = msg.properties.appId || ""

 logger.verbose(`received ${event}`, logMessage)

  var text

  switch (event) {

    case "github:pull_request:closed:handled":
    case "github:pull_request:opened:handled":
    case "github:pull_request:synchronize:handled":
    case "bitbucket:pullrequest:created:handled":
    case "bitbucket:pullrequest:updated:handled":
    case "bitbucket:pullrequest:fulfilled:handled":
    case "bitbucket:pullrequest:rejected:handled":
      sendToRocketChat(project, message, '#E8E8E8', ':information_source:', channelWrapperLogs, msg, appId)
      break;
    case "github:delete:handled":
    case "github:push:handled":
    case "bitbucket:repo:push:handled":
    case "gitlab:push:handled":
      console.log(`tyler: ${JSON.stringify(meta)}`);
      text = `*[${meta.projectName}]* [${meta.branchName}](${meta.repoUrl}/tree/${meta.branchName})`
      if (meta.shortSha){
        text = `${text} ([${meta.shortSha}](${meta.commitUrl}))`
      }
      text = `${text} pushed in [${meta.pathWithNamespace}](${meta.repoUrl})`
      sendToRocketChat(project, text, '#E8E8E8', ':information_source:', channelWrapperLogs, msg, appId)
      break;

    case "rest:deploy:receive":
    case "rest:remove:receive":
    case "rest:promote:receive":
      sendToRocketChat(project, message, '#E8E8E8', ':information_source:', channelWrapperLogs, msg, appId)
      break;

    case "task:deploy-openshift:finished":
    case "task:remove-openshift:finished":
    case "task:remove-openshift-resources:finished":
    case "task:builddeploy-openshift:complete":
      text = `*[${meta.projectName}]* `
      if (meta.shortSha) {
        text = `${text} \`${meta.branchName}\` (${meta.shortSha})`
      } else {
        text = `${text} \`${meta.branchName}\``
      }
      text = `${text} Build \`${meta.buildName}\` complete. ${meta.logLink} \n ${meta.route}\n ${meta.routes.join("\n")}`
      sendToRocketChat(project, text, 'lawngreen', ':white_check_mark:', channelWrapperLogs, msg, appId)
      break;

    case "task:deploy-openshift:retry":
    case "task:remove-openshift:retry":
    case "task:remove-openshift-resources:retry":
      sendToRocketChat(project, message, 'gold', ':warning:', channelWrapperLogs, msg, appId)
      break;

    case "task:deploy-openshift:error":
    case "task:remove-openshift:error":
    case "task:remove-openshift-resources:error":
    case "task:builddeploy-openshift:failed":
      sendToRocketChat(project, message, 'red', ':bangbang:', channelWrapperLogs, msg, appId)
      break;

    case "github:pull_request:closed:CannotDeleteProductionEnvironment":
    case "github:push:CannotDeleteProductionEnvironment":
    case "bitbucket:repo:push:CannotDeleteProductionEnvironment":
    case "gitlab:push:CannotDeleteProductionEnvironment":
    case "rest:remove:CannotDeleteProductionEnvironment":
      sendToRocketChat(project, message, 'gold', ':warning:', channelWrapperLogs, msg, appId)
      break;

    case "unresolvedProject:webhooks2tasks":
    case "unhandledWebhook":
    case "webhooks:receive":
    case "task:deploy-openshift:start":
    case "task:remove-openshift:start":
    case "task:remove-openshift-resources:start":
    case "task:builddeploy-openshift:running":
      // known logs entries that should never go to RocketChat
      channelWrapperLogs.ack(msg)
      break;

    default:
      logger.info(`unhandled log message ${event} ${JSON.stringify(logMessage)}`)
      return channelWrapperLogs.ack(msg)
  }

}

const sendToRocketChat = async (project, message, color, emoji, channelWrapperLogs, msg, appId) => {
  let projectRocketChats;
  try {
    projectRocketChats = await getRocketChatInfoForProject(project)
  }
  catch (error) {
    logger.error(`No RocketChat information found, error: ${error}`)
    return channelWrapperLogs.ack(msg)
  }
  projectRocketChats.forEach(async (projectRocketChat) => {
    const { channel, webhook } = projectRocketChat;
    const rocketchat = new URL(webhook);

    var data = JSON.stringify({
      channel: `#${channel}`,
      attachments: [{
        text: `${emoji} ${message}`,
        color: color,
        fields: [
          {
            "short": true,
            "title": "Source",
            "value": appId
          }
        ],
      }]
    });

    var options = {
      hostname: rocketchat.hostname,
      port: rocketchat.port,
      path: rocketchat.pathname,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': data.length
      }
    };

    var req = http.request(options, function(res) {
      res.setEncoding('utf8');
    });

    req.on('error', function(e) {
      logger.error(`problem with request: ${e.message}`);
    });
    req.write(data);
    req.end();
  });
  channelWrapperLogs.ack(msg)
  return
}

module.exports = readFromRabbitMQ;
<|endoftext|>


<commit_before>/**
 * Open System constructor
 *
 * @class Roguelike.Systems.Open
 * @classdesc The Open system handles opening entities and making sure the collision is turned of after they are opened
 *
 * @param {Roguelike.Game} game - Reference to the currently running game
 */
Roguelike.Systems.Open = function(game) {

	/**
	 * @property {Roguelike.Game} game - Reference to the current game object
	 */
	this.game = game;

};

Roguelike.Systems.Open.prototype = {

	/**
	 * Performs the needed operations for this specific system on one entity
	 * @protected
	 *
	 * @param {Roguelike.Entity} entity - The entity that is being processed by this system
	 */
	handleSingleEntity: function(entity) {

		//Get the components from the current entity and store them temporarily in a variable
		var canOpenComponent = entity.getComponent("canOpen");
		var spriteComponent = entity.getComponent("sprite");
		var positionComponent = entity.getComponent("position");
		var collideComponent = entity.getComponent("collide");

		//Action to open the door
		if(canOpenComponent.state !== "open") {

			//Change the door's state to open
			canOpenComponent.state = "open";

			//Change the sprite to open
			spriteComponent.tile += 1;

			//Make sure the collide component doesn't say it collides anymore
			collideComponent.collide = false;

			//Make sure the tile that this openable entity is on doesn't block light anymore
			this.game.map.tiles[positionComponent.position.x][positionComponent.position.y].blockLight = false;

		}

	}

};
<commit_msg>When you open something that is able to open, the text in the tooltip get's changed to open.<commit_after>/**
 * Open System constructor
 *
 * @class Roguelike.Systems.Open
 * @classdesc The Open system handles opening entities and making sure the collision is turned of after they are opened
 *
 * @param {Roguelike.Game} game - Reference to the currently running game
 */
Roguelike.Systems.Open = function(game) {

	/**
	 * @property {Roguelike.Game} game - Reference to the current game object
	 */
	this.game = game;

};

Roguelike.Systems.Open.prototype = {

	/**
	 * Performs the needed operations for this specific system on one entity
	 * @protected
	 *
	 * @param {Roguelike.Entity} entity - The entity that is being processed by this system
	 */
	handleSingleEntity: function(entity) {

		//Get the components from the current entity and store them temporarily in a variable
		var canOpenComponent = entity.getComponent("canOpen");
		var spriteComponent = entity.getComponent("sprite");
		var positionComponent = entity.getComponent("position");
		var collideComponent = entity.getComponent("collide");
		var tooltipComponent = entity.getComponent("tooltip");

		//Action to open the door
		if(canOpenComponent.state !== "open") {

			//Change the door's state to open
			canOpenComponent.state = "open";

			//Change the sprite to open
			spriteComponent.tile += 1;

			//Make sure the collide component doesn't say it collides anymore
			collideComponent.collide = false;

			tooltipComponent.type = ["Open"];

			//Make sure the tile that this openable entity is on doesn't block light anymore
			this.game.map.tiles[positionComponent.position.x][positionComponent.position.y].blockLight = false;

		}

	}

};
<|endoftext|>