<commit_before>import { injectIntl } from "react-intl";
import mixin from "reactjs-mixin";
import React, { PropTypes } from "react";
import { routerShape } from "react-router";
import { Hooks } from "PluginSDK";

import Page from "#SRC/js/components/Page";
import RouterUtil from "#SRC/js/utils/RouterUtil";
import StringUtil from "#SRC/js/utils/StringUtil";
import TabsMixin from "#SRC/js/mixins/TabsMixin";
import UserActions from "#SRC/js/constants/UserActions";
import { isSDKService } from "#SRC/js/utils/ServiceUtil";

import ActionKeys from "../../constants/ActionKeys";
import MarathonErrorUtil from "../../utils/MarathonErrorUtil";
import Service from "../../structs/Service";
import ServiceTree from "../../structs/ServiceTree";
import ServiceActionLabels from "../../constants/ServiceActionLabels";
import ServiceBreadcrumbs from "../../components/ServiceBreadcrumbs";
import ServiceModals from "../../components/modals/ServiceModals";
import ServiceActionDisabledModal
  from "../../components/modals/ServiceActionDisabledModal";
import {
  DELETE,
  EDIT,
  OPEN,
  RESTART,
  RESUME,
  SCALE,
  SUSPEND
} from "../../constants/ServiceActionItem";

const METHODS_TO_BIND = [
  "handleEditClearError",
  "handleActionDisabledModalOpen",
  "handleActionDisabledModalClose"
];

class ServiceDetail extends mixin(TabsMixin) {
  constructor() {
    super(...arguments);

    this.tabs_tabs = {
      "/services/overview/:id/tasks": "Instances",
      "/services/overview/:id/configuration": "Configuration",
      "/services/overview/:id/debug": "Debug"
    };

    this.state = {
      actionDisabledID: null,
      actionDisabledModalOpen: false,
      currentTab: Object.keys(this.tabs_tabs).shift()
    };

    METHODS_TO_BIND.forEach(method => {
      this[method] = this[method].bind(this);
    });
  }

  componentWillMount() {
    super.componentWillMount(...arguments);
    this.updateCurrentTab();
    this.checkForVolumes();
  }

  componentWillReceiveProps(nextProps) {
    super.componentWillReceiveProps(...arguments);
    this.updateCurrentTab(nextProps);
    this.checkForVolumes();
  }

  updateCurrentTab(props = this.props) {
    const { routes } = props;
    const currentTab = RouterUtil.reconstructPathFromRoutes(routes);
    if (currentTab != null) {
      this.setState({ currentTab });
    }
  }

  handleEditClearError() {
    this.props.clearError(ActionKeys.SERVICE_EDIT);
  }

  onActionsItemSelection(actionID) {
    const { service } = this.props;
    const isGroup = service instanceof ServiceTree;
    let containsSDKService = false;

    if (isGroup) {
      containsSDKService =
        service.findItem(function(item) {
          return item instanceof Service && isSDKService(item);
        }) != null;
    }

    if (
      (containsSDKService || isSDKService(service)) &&
      !Hooks.applyFilter(
        "isEnabledSDKAction",
        actionID === EDIT || actionID === OPEN,
        actionID
      )
    ) {
      this.handleActionDisabledModalOpen(actionID);
    } else {
      this.handleServiceAction(actionID);
    }
  }

  handleServiceAction(actionID) {
    const { modalHandlers, router } = this.context;
    const { service } = this.props;

    switch (actionID) {
      case EDIT:
        router.push(
          `/services/detail/${encodeURIComponent(service.getId())}/edit/`
        );
        break;
      case SCALE:
        modalHandlers.scaleService({ service });
        break;
      case OPEN:
        modalHandlers.openServiceUI({ service });
        break;
      case RESTART:
        modalHandlers.restartService({ service });
        break;
      case RESUME:
        modalHandlers.resumeService({ service });
        break;
      case SUSPEND:
        modalHandlers.suspendService({ service });
        break;
      case DELETE:
        modalHandlers.deleteService({ service });
        break;
    }
  }

  handleActionDisabledModalOpen(actionDisabledID) {
    this.setState({ actionDisabledModalOpen: true, actionDisabledID });
  }

  handleActionDisabledModalClose() {
    this.setState({ actionDisabledModalOpen: false, actionDisabledID: null });
  }

  hasVolumes() {
    return (
      !!this.props.service &&
      this.props.service.getVolumes().getItems().length > 0
    );
  }

  checkForVolumes() {
    // Add the Volumes tab if it isn't already there and the service has
    // at least one volume.
    if (
      this.tabs_tabs["/services/overview/:id/volumes"] == null &&
      this.hasVolumes()
    ) {
      this.tabs_tabs["/services/overview/:id/volumes"] = "Volumes";
      this.forceUpdate();
    }
  }

  getActions() {
    const { service } = this.props;
    const instanceCount = service.getInstancesCount();
    const isSDK = isSDKService(service);

    const actions = [];

    if (
      service instanceof Service &&
      !isSDKService(service) &&
      service.getWebURL() != null &&
      service.getWebURL() !== ""
    ) {
      actions.push({
        label: this.props.intl.formatMessage({
          id: ServiceActionLabels.open
        }),
        onItemSelect: this.onActionsItemSelection.bind(this, OPEN)
      });
    }

    actions.push({
      label: "Edit",
      onItemSelect: this.onActionsItemSelection.bind(this, EDIT)
    });

    if (instanceCount > 0 && !isSDK) {
      actions.push({
        label: "Restart",
        onItemSelect: this.onActionsItemSelection.bind(this, RESTART)
      });
    }
    if (!service.getLabels().MARATHON_SINGLE_INSTANCE_APP) {
      actions.push({
        label: "Scale",
        onItemSelect: this.onActionsItemSelection.bind(this, SCALE)
      });
    }

    if (instanceCount > 0 && !isSDK) {
      actions.push({
        label: "Suspend",
        onItemSelect: this.onActionsItemSelection.bind(this, SUSPEND)
      });
    }

    if (instanceCount === 0 && !isSDK) {
      actions.push({
        label: "Resume",
        onItemSelect: this.onActionsItemSelection.bind(this, RESUME)
      });
    }

    actions.push({
      className: "text-danger",
      label: StringUtil.capitalize(UserActions.DELETE),
      onItemSelect: this.onActionsItemSelection.bind(this, DELETE)
    });

    return actions;
  }

  getTabs() {
    const { service: { id } } = this.props;
    const routePrefix = `/services/detail/${encodeURIComponent(id)}`;

    const tabs = [
      { label: "Instances", routePath: `${routePrefix}/tasks` },
      { label: "Configuration", routePath: `${routePrefix}/configuration` },
      { label: "Debug", routePath: `${routePrefix}/debug` }
    ];

    if (this.hasVolumes()) {
      tabs.push({
        label: "Volumes",
        routePath: `${routePrefix}/volumes`
      });
    }

    return tabs;
  }

  render() {
    const { children, actions, errors, params, routes, service } = this.props;
    const { actionDisabledModalOpen, actionDisabledID } = this.state;
    const breadcrumbs = <ServiceBreadcrumbs serviceID={service.id} />;
    const clonedProps = {
      params,
      routes,
      service,
      errors: MarathonErrorUtil.parseErrors(errors[ActionKeys.SERVICE_EDIT]),
      onClearError: this.handleEditClearError,
      onEditClick: actions.editService,
      volumes: service.getVolumes().getItems()
    };

    // TODO (DCOS_OSS-1038): Move cloned props to route parameters
    const clonedChildren = React.Children.map(children, function(child) {
      // Only add props to children that are not ServiceModals
      if (child.type === ServiceModals) {
        return child;
      }

      return React.cloneElement(child, clonedProps);
    });

    return (
      <Page>
        <Page.Header
          actions={this.getActions()}
          tabs={this.getTabs()}
          breadcrumbs={breadcrumbs}
          iconID="services"
        />
        {clonedChildren}
        <ServiceActionDisabledModal
          actionID={actionDisabledID}
          open={actionDisabledModalOpen}
          onClose={this.handleActionDisabledModalClose}
          service={service}
        />
      </Page>
    );
  }
}

ServiceDetail.contextTypes = {
  clearError() {},
  modalHandlers: PropTypes.shape({
    scaleService: PropTypes.func,
    restartService: PropTypes.func,
    suspendService: PropTypes.func,
    deleteService: PropTypes.func,
    openService: PropTypes.func
  }).isRequired,
  router: routerShape
};

ServiceDetail.propTypes = {
  actions: PropTypes.object.isRequired,
  clearError: PropTypes.func,
  errors: PropTypes.object.isRequired,
  params: PropTypes.object.isRequired,
  service: PropTypes.instanceOf(Service).isRequired,
  children: PropTypes.node
};

module.exports = injectIntl(ServiceDetail);
<commit_msg>feat(ServiceDetail): Rename Instances to Tasks<commit_after>import { injectIntl } from "react-intl";
import mixin from "reactjs-mixin";
import React, { PropTypes } from "react";
import { routerShape } from "react-router";
import { Hooks } from "PluginSDK";

import Page from "#SRC/js/components/Page";
import RouterUtil from "#SRC/js/utils/RouterUtil";
import StringUtil from "#SRC/js/utils/StringUtil";
import TabsMixin from "#SRC/js/mixins/TabsMixin";
import UserActions from "#SRC/js/constants/UserActions";
import { isSDKService } from "#SRC/js/utils/ServiceUtil";

import ActionKeys from "../../constants/ActionKeys";
import MarathonErrorUtil from "../../utils/MarathonErrorUtil";
import Service from "../../structs/Service";
import ServiceTree from "../../structs/ServiceTree";
import ServiceActionLabels from "../../constants/ServiceActionLabels";
import ServiceBreadcrumbs from "../../components/ServiceBreadcrumbs";
import ServiceModals from "../../components/modals/ServiceModals";
import ServiceActionDisabledModal
  from "../../components/modals/ServiceActionDisabledModal";
import {
  DELETE,
  EDIT,
  OPEN,
  RESTART,
  RESUME,
  SCALE,
  SUSPEND
} from "../../constants/ServiceActionItem";

const METHODS_TO_BIND = [
  "handleEditClearError",
  "handleActionDisabledModalOpen",
  "handleActionDisabledModalClose"
];

class ServiceDetail extends mixin(TabsMixin) {
  constructor() {
    super(...arguments);

    this.tabs_tabs = {
      "/services/overview/:id/tasks": "Instances",
      "/services/overview/:id/configuration": "Configuration",
      "/services/overview/:id/debug": "Debug"
    };

    this.state = {
      actionDisabledID: null,
      actionDisabledModalOpen: false,
      currentTab: Object.keys(this.tabs_tabs).shift()
    };

    METHODS_TO_BIND.forEach(method => {
      this[method] = this[method].bind(this);
    });
  }

  componentWillMount() {
    super.componentWillMount(...arguments);
    this.updateCurrentTab();
    this.checkForVolumes();
  }

  componentWillReceiveProps(nextProps) {
    super.componentWillReceiveProps(...arguments);
    this.updateCurrentTab(nextProps);
    this.checkForVolumes();
  }

  updateCurrentTab(props = this.props) {
    const { routes } = props;
    const currentTab = RouterUtil.reconstructPathFromRoutes(routes);
    if (currentTab != null) {
      this.setState({ currentTab });
    }
  }

  handleEditClearError() {
    this.props.clearError(ActionKeys.SERVICE_EDIT);
  }

  onActionsItemSelection(actionID) {
    const { service } = this.props;
    const isGroup = service instanceof ServiceTree;
    let containsSDKService = false;

    if (isGroup) {
      containsSDKService =
        service.findItem(function(item) {
          return item instanceof Service && isSDKService(item);
        }) != null;
    }

    if (
      (containsSDKService || isSDKService(service)) &&
      !Hooks.applyFilter(
        "isEnabledSDKAction",
        actionID === EDIT || actionID === OPEN,
        actionID
      )
    ) {
      this.handleActionDisabledModalOpen(actionID);
    } else {
      this.handleServiceAction(actionID);
    }
  }

  handleServiceAction(actionID) {
    const { modalHandlers, router } = this.context;
    const { service } = this.props;

    switch (actionID) {
      case EDIT:
        router.push(
          `/services/detail/${encodeURIComponent(service.getId())}/edit/`
        );
        break;
      case SCALE:
        modalHandlers.scaleService({ service });
        break;
      case OPEN:
        modalHandlers.openServiceUI({ service });
        break;
      case RESTART:
        modalHandlers.restartService({ service });
        break;
      case RESUME:
        modalHandlers.resumeService({ service });
        break;
      case SUSPEND:
        modalHandlers.suspendService({ service });
        break;
      case DELETE:
        modalHandlers.deleteService({ service });
        break;
    }
  }

  handleActionDisabledModalOpen(actionDisabledID) {
    this.setState({ actionDisabledModalOpen: true, actionDisabledID });
  }

  handleActionDisabledModalClose() {
    this.setState({ actionDisabledModalOpen: false, actionDisabledID: null });
  }

  hasVolumes() {
    return (
      !!this.props.service &&
      this.props.service.getVolumes().getItems().length > 0
    );
  }

  checkForVolumes() {
    // Add the Volumes tab if it isn't already there and the service has
    // at least one volume.
    if (
      this.tabs_tabs["/services/overview/:id/volumes"] == null &&
      this.hasVolumes()
    ) {
      this.tabs_tabs["/services/overview/:id/volumes"] = "Volumes";
      this.forceUpdate();
    }
  }

  getActions() {
    const { service } = this.props;
    const instanceCount = service.getInstancesCount();
    const isSDK = isSDKService(service);

    const actions = [];

    if (
      service instanceof Service &&
      !isSDKService(service) &&
      service.getWebURL() != null &&
      service.getWebURL() !== ""
    ) {
      actions.push({
        label: this.props.intl.formatMessage({
          id: ServiceActionLabels.open
        }),
        onItemSelect: this.onActionsItemSelection.bind(this, OPEN)
      });
    }

    actions.push({
      label: "Edit",
      onItemSelect: this.onActionsItemSelection.bind(this, EDIT)
    });

    if (instanceCount > 0 && !isSDK) {
      actions.push({
        label: "Restart",
        onItemSelect: this.onActionsItemSelection.bind(this, RESTART)
      });
    }
    if (!service.getLabels().MARATHON_SINGLE_INSTANCE_APP) {
      actions.push({
        label: "Scale",
        onItemSelect: this.onActionsItemSelection.bind(this, SCALE)
      });
    }

    if (instanceCount > 0 && !isSDK) {
      actions.push({
        label: "Suspend",
        onItemSelect: this.onActionsItemSelection.bind(this, SUSPEND)
      });
    }

    if (instanceCount === 0 && !isSDK) {
      actions.push({
        label: "Resume",
        onItemSelect: this.onActionsItemSelection.bind(this, RESUME)
      });
    }

    actions.push({
      className: "text-danger",
      label: StringUtil.capitalize(UserActions.DELETE),
      onItemSelect: this.onActionsItemSelection.bind(this, DELETE)
    });

    return actions;
  }

  getTabs() {
    const { service: { id } } = this.props;
    const routePrefix = `/services/detail/${encodeURIComponent(id)}`;

    const tabs = [
      { label: "Tasks", routePath: `${routePrefix}/tasks` },
      { label: "Configuration", routePath: `${routePrefix}/configuration` },
      { label: "Debug", routePath: `${routePrefix}/debug` }
    ];

    if (this.hasVolumes()) {
      tabs.push({
        label: "Volumes",
        routePath: `${routePrefix}/volumes`
      });
    }

    return tabs;
  }

  render() {
    const { children, actions, errors, params, routes, service } = this.props;
    const { actionDisabledModalOpen, actionDisabledID } = this.state;
    const breadcrumbs = <ServiceBreadcrumbs serviceID={service.id} />;
    const clonedProps = {
      params,
      routes,
      service,
      errors: MarathonErrorUtil.parseErrors(errors[ActionKeys.SERVICE_EDIT]),
      onClearError: this.handleEditClearError,
      onEditClick: actions.editService,
      volumes: service.getVolumes().getItems()
    };

    // TODO (DCOS_OSS-1038): Move cloned props to route parameters
    const clonedChildren = React.Children.map(children, function(child) {
      // Only add props to children that are not ServiceModals
      if (child.type === ServiceModals) {
        return child;
      }

      return React.cloneElement(child, clonedProps);
    });

    return (
      <Page>
        <Page.Header
          actions={this.getActions()}
          tabs={this.getTabs()}
          breadcrumbs={breadcrumbs}
          iconID="services"
        />
        {clonedChildren}
        <ServiceActionDisabledModal
          actionID={actionDisabledID}
          open={actionDisabledModalOpen}
          onClose={this.handleActionDisabledModalClose}
          service={service}
        />
      </Page>
    );
  }
}

ServiceDetail.contextTypes = {
  clearError() {},
  modalHandlers: PropTypes.shape({
    scaleService: PropTypes.func,
    restartService: PropTypes.func,
    suspendService: PropTypes.func,
    deleteService: PropTypes.func,
    openService: PropTypes.func
  }).isRequired,
  router: routerShape
};

ServiceDetail.propTypes = {
  actions: PropTypes.object.isRequired,
  clearError: PropTypes.func,
  errors: PropTypes.object.isRequired,
  params: PropTypes.object.isRequired,
  service: PropTypes.instanceOf(Service).isRequired,
  children: PropTypes.node
};

module.exports = injectIntl(ServiceDetail);
<|endoftext|>


<commit_before>
var sys = require("sys");
var p = require("path");
var fs = require("fs");
var spawn = require("child_process").spawn;
var exec = require("child_process").exec;
var fileExtensionPattern;
var program, port;
// A program name which is "impossible" for anyone to choose, which represents no program.
var NO_PROGRAM = "__none__.coffee";
var programExt;
exports.run = run;

function run (args) {
  var arg, next, watch, extensions, executor;
  while (arg = args.shift()) {
    if (arg === "--help" || arg === "-h" || arg === "-?") {
      return help();
    } else if (arg === "--watch-only" || arg === "-o") {
      program = NO_PROGRAM;
    } else if (arg === "--watch" || arg === "-w") {
      watch = args.shift();
    } else if (arg === "--port" || arg === "-p") {
      port = args.shift();
    } else if (arg === "--extensions" || arg === "-e") {
      extensions = args.shift();
    } else if (arg === "--exec" || arg === "-x") {
      executor = args.shift();
    } else if (arg.indexOf("-") && !args.length) {
      // Assume last arg is the program
      program = arg;
    }
  }
  if (!program) {
    //return help();
    var pwdFiles = fs.readdirSync('.');
    var autoRunFiles = ["app.js", "manage.py"]
    for (var i = 0; i < autoRunFiles.length; i++) {
      if (program) break;
      if (pwdFiles.indexOf(autoRunFiles[i]) > -1) program=autoRunFiles[i];
    }
    if (!program) {
      program = NO_PROGRAM;
    }

  }
  if (!watch) {
    watch = ".";
  }

  programExt = program.match(/.*\.(.*)/);
  programExt = programExt && programExt[1];

  if (!extensions) {
    // If no extensions passed try to guess from the program
    extensions = "node|js|styl|eco|coffee|jade";
    if (programExt && extensions.indexOf(programExt) == -1)
      extensions += "|" + programExt;
  }
  fileExtensionPattern = new RegExp(".*\.(" + extensions + ")$");

  if (!executor) {
    if (programExt === "coffee") {
      executor = "coffee";
    } else if (programExt === "py") {
      executor = "python";
    } else if (programExt === "js") {
      executor = "node";
    } else {
      throw "Extension `" + programExt + "` not supported.";
    }
  }

  sys.puts("")
  sys.debug("Running node-supervisor with");
  sys.debug("  program '" + program + "'");
  sys.debug("  --watch '" + watch + "'");
  sys.debug("  --extensions '" + extensions + "'");
  sys.debug("  --exec '" + executor + "'");
  sys.puts("")

  // if we have a program, then run it, and restart when it crashes.
  // if we have a watch folder, then watch the folder for changes and restart the prog

  if (program !== NO_PROGRAM) startProgram(program, executor);
  var watchItems = watch.split(',');
  watchItems.forEach(function (watchItem) {
    if (!watchItem.match(/^\/.*/)) { // watch is not an absolute path
      // convert watch item to absolute path
      watchItem = process.cwd() + '/' + watchItem;
    }
    sys.debug("Watching directory '" + watchItem + "' for changes.");
    findAllWatchFiles(watchItem, watchGivenFile);
  });
};

function print (m, n) { sys.print(m+(!n?"\n":"")); return print }

function help () {
  print
    ("")
    ("Node Supervisor is used to restart programs when they crash.")
    ("It can also be used to restart programs when a *.js file changes.")
    ("")
    ("Usage:")
    ("  supervisor [options] <program>")
    ("")
    ("Required:")
    ("  <program>")
    ("    The program to run.")
    ("")
    ("Options:")
    ("  -w|--watch <watchItems>")
    ("    A comma-delimited list of folders or js files to watch for changes.")
    ("    When a change to a js file occurs, reload the program")
    ("    Default is '.'")
    ("")
    ("  -e|--extensions <extensions>")
    ("    Specific file extensions to watch in addition to defaults.")
    ("    Used when --watch option includes folders")
    ("    Default is 'node|js'")
    ("")
    ("  -x|--exec <executable>")
    ("    The executable that runs the specified program.")
    ("    Default is 'node'")
    ("")
    ("  -h|--help|-?")
    ("    Display these usage instructions.")
    ("")
    ("Examples:")
    ("  supervisor myapp.js")
    ("  supervisor myapp.coffee")
    ("  supervisor -w scripts -e myext -x myrunner myapp")
    ("  supervisor -w lib -w server.js -w config.js server.js")
    ("")
}

function startProgram (prog, exec) {
  var cl_args;
  if (prog == 'manage.py') {
    program = NO_PROGRAM
    // special case for Django program.
    cl_args = [prog, 'runserver', '0.0.0.0:' + (port || 8000)];
  } else {
    cl_args = [prog];
  }
  sys.debug("Starting child process with '" + exec + " " + cl_args.join(' ') + "'");
  var child = exports.child = spawn(exec, cl_args);
  child.stdout.addListener("data", function (chunk) { chunk && sys.print(chunk) });
  child.stderr.addListener("data", function (chunk) { chunk && sys.debug(chunk) });
  child.addListener("exit", function () { startProgram(prog, exec) });
}

var timer = null, counter = -1, mtime = null;

function getExtension(filename) {
  var programExt = filename.match(/.*\.([^\.]*)$/);
  return programExt && programExt[1];
}

function stopCrashing () {
  if (counter > 3) throw new Error("Crashing too much, shutting down");
  else counter = -1;
}

var lastEvt = {}; // Hash of all watched files.

function watchGivenFile (watch) {
  //fs.watchFile(watch, function crash (oldStat, newStat) {
  if(lastEvt[watch]) return;
  lastEvt[watch] = (new Date()).valueOf()
  fs.watch(watch, function crash (evt, filename) {
    // we only care about modification time, not access time.
    /*if (
      newStat.mtime.getTime() === oldStat.mtime.getTime()
    ) return;
    */
    //DEBOUNCE
    now = (new Date).valueOf();
    if (lastEvt[watch]) {
      if (now - lastEvt[watch] < 2000) {
        return;
      }
    }
    lastEvt[watch] = now;

    // Handle new files. Re-watch parent directory.
    if (evt === 'rename' &! watch.match(fileExtensionPattern)) {
      findAllWatchFiles(watch, watchGivenFile);
    }

    if (counter === -1) {
      timer = setTimeout(stopCrashing, 400);
    }
    counter ++;

    var child = exports.child;
    var extension = getExtension(watch);
    sys.debug("detected change at "+watch+" - "+evt+" ext:"+extension);
    if ("coffee" === extension) {
      sys.debug("compiling with coffeescript.");
      exec("coffee -m -c "+watch,function(err, stderr, stdout) {
            if (err) sys.debug(err);
            if (stderr) sys.debug(stderr);
            if (stdout) sys.debug(stdout);
      });
      // The JS file update should cause a restart, so don't do it here.
      /*if (programExt === "coffee") {
        // Don't restart for client side updates.
        if (program !== NO_PROGRAM && watch.indexOf('public/') === -1) process.kill(child.pid);
      }*/
    } else if (extension === "styl") {
      sys.debug('compiling with stylus.');
      exec("stylus "+watch,function(err, stderr, stdout) {
            if (err) sys.debug(err);
            if (stderr) sys.debug(stderr);
            if (stdout) sys.debug(stdout);
      });
    } else if (extension === "eco") {
      sys.debug('compiling with eco.');
      exec("eco -o "+p.dirname(watch)+" "+watch,function(err, stderr, stdout) {
            if (err) sys.debug(err);
            if (stderr) sys.debug(stderr);
            if (stdout) sys.debug(stdout);
      });
    } else if (extension === "jade") {
      if (watch.indexOf("client") > -1) {
        sys.debug('compiling with clientjade wrapper.');
        exec("clientjade.py " + p.dirname(watch) + " ./public",function(err, stderr, stdout) {
              if (err) sys.debug(err);
              if (stderr) sys.debug(stderr);
              if (stdout) sys.debug(stdout);
        });
      }
    } else if (extension === "js" && programExt === "coffee") {
      // Do nothing. TODO: why is this here.
    } else if (extension === "js" && watch.indexOf("public") !== -1) {
      // JS updates in the client folder don't trigger a restart.
    } else {

      if (program !== NO_PROGRAM) process.kill(child.pid);
    }
  });
}

var findAllWatchFiles = function(path, callback) {
  fs.stat(path, function(err, stats){
    if (err) {
      sys.error('Error retrieving stats for file: ' + path);
    } else {
      if (stats.isDirectory()) {
        //callback(p.normalize(path));
        fs.readdir(path, function(err, fileNames) {
          if(err) {
            sys.puts('Error reading path: ' + path);
          }
          else {
            fileNames.forEach(function (fileName) {
              if ( fileName.charAt(0) !== '.'
//                && fileName !== 'node_modules'
                && fileName !== 'components'
                && fileName !== 'bower_components'
                && fileName !== 'run'
                )
                findAllWatchFiles(path + '/' + fileName, callback);
            });
          }
        });
      } else {

        if (path.match(fileExtensionPattern)) {
          callback(p.normalize(path));
        }
      }
    }
  });
}
<commit_msg>new scripts<commit_after>
var sys = require("sys");
var p = require("path");
var fs = require("fs");
var spawn = require("child_process").spawn;
var exec = require("child_process").exec;
var fileExtensionPattern;
var program, port;
// A program name which is "impossible" for anyone to choose, which represents no program.
var NO_PROGRAM = "__none__.coffee";
var programExt;
exports.run = run;

function run (args) {
  var arg, next, watch, extensions, executor;
  while (arg = args.shift()) {
    if (arg === "--help" || arg === "-h" || arg === "-?") {
      return help();
    } else if (arg === "--watch-only" || arg === "-o") {
      program = NO_PROGRAM;
    } else if (arg === "--watch" || arg === "-w") {
      watch = args.shift();
    } else if (arg === "--port" || arg === "-p") {
      port = args.shift();
    } else if (arg === "--extensions" || arg === "-e") {
      extensions = args.shift();
    } else if (arg === "--exec" || arg === "-x") {
      executor = args.shift();
    } else if (arg.indexOf("-") && !args.length) {
      // Assume last arg is the program
      program = arg;
    }
  }
  if (!program) {
    //return help();
    var pwdFiles = fs.readdirSync('.');
    var autoRunFiles = ["app.js", "manage.py"]
    for (var i = 0; i < autoRunFiles.length; i++) {
      if (program) break;
      if (pwdFiles.indexOf(autoRunFiles[i]) > -1) program=autoRunFiles[i];
    }
    if (!program) {
      program = NO_PROGRAM;
    }

  }
  if (!watch) {
    watch = ".";
  }

  programExt = program.match(/.*\.(.*)/);
  programExt = programExt && programExt[1];

  if (!extensions) {
    // If no extensions passed try to guess from the program
    extensions = "node|js|styl|eco|coffee|jade";
    if (programExt && extensions.indexOf(programExt) == -1)
      extensions += "|" + programExt;
  }
  fileExtensionPattern = new RegExp(".*\.(" + extensions + ")$");

  if (!executor) {
    if (programExt === "coffee") {
      executor = "coffee";
    } else if (programExt === "py") {
      executor = "python";
    } else if (programExt === "js") {
      executor = "node";
    } else {
      throw "Extension `" + programExt + "` not supported.";
    }
  }

  sys.puts("")
  sys.debug("Running node-supervisor with");
  sys.debug("  program '" + program + "'");
  sys.debug("  --watch '" + watch + "'");
  sys.debug("  --extensions '" + extensions + "'");
  sys.debug("  --exec '" + executor + "'");
  sys.puts("")

  // if we have a program, then run it, and restart when it crashes.
  // if we have a watch folder, then watch the folder for changes and restart the prog

  if (program !== NO_PROGRAM) startProgram(program, executor);
  var watchItems = watch.split(',');
  watchItems.forEach(function (watchItem) {
    if (!watchItem.match(/^\/.*/)) { // watch is not an absolute path
      // convert watch item to absolute path
      watchItem = process.cwd() + '/' + watchItem;
    }
    sys.debug("Watching directory '" + watchItem + "' for changes.");
    findAllWatchFiles(watchItem, watchGivenFile);
  });
};

function print (m, n) { sys.print(m+(!n?"\n":"")); return print }

function help () {
  print
    ("")
    ("Node Supervisor is used to restart programs when they crash.")
    ("It can also be used to restart programs when a *.js file changes.")
    ("")
    ("Usage:")
    ("  supervisor [options] <program>")
    ("")
    ("Required:")
    ("  <program>")
    ("    The program to run.")
    ("")
    ("Options:")
    ("  -w|--watch <watchItems>")
    ("    A comma-delimited list of folders or js files to watch for changes.")
    ("    When a change to a js file occurs, reload the program")
    ("    Default is '.'")
    ("")
    ("  -e|--extensions <extensions>")
    ("    Specific file extensions to watch in addition to defaults.")
    ("    Used when --watch option includes folders")
    ("    Default is 'node|js'")
    ("")
    ("  -x|--exec <executable>")
    ("    The executable that runs the specified program.")
    ("    Default is 'node'")
    ("")
    ("  -h|--help|-?")
    ("    Display these usage instructions.")
    ("")
    ("Examples:")
    ("  supervisor myapp.js")
    ("  supervisor myapp.coffee")
    ("  supervisor -w scripts -e myext -x myrunner myapp")
    ("  supervisor -w lib -w server.js -w config.js server.js")
    ("")
}

function startProgram (prog, exec) {
  var cl_args;
  if (prog == 'manage.py') {
    program = NO_PROGRAM
    // special case for Django program.
    cl_args = [prog, 'runserver', '0.0.0.0:' + (port || 8000)];
  } else {
    cl_args = [prog];
  }
  sys.debug("Starting child process with '" + exec + " " + cl_args.join(' ') + "'");
  var child = exports.child = spawn(exec, cl_args);
  child.stdout.addListener("data", function (chunk) { chunk && sys.print(chunk) });
  child.stderr.addListener("data", function (chunk) { chunk && sys.debug(chunk) });
  child.addListener("exit", function () { startProgram(prog, exec) });
}

var timer = null, counter = -1, mtime = null;

function getExtension(filename) {
  var programExt = filename.match(/.*\.([^\.]*)$/);
  return programExt && programExt[1];
}

function stopCrashing () {
  if (counter > 3) throw new Error("Crashing too much, shutting down");
  else counter = -1;
}

var lastEvt = {}; // Hash of all watched files.

function watchGivenFile (watch) {
  if(lastEvt[watch]) return;
  lastEvt[watch] = (new Date()).valueOf()
  fs.watchFile(watch, function crash() {
    // we only care about modification time, not access time.
    /*if (
      newStat.mtime.getTime() === oldStat.mtime.getTime()
    ) return;
    */
    //DEBOUNCE
    filename = watch
    now = (new Date).valueOf();
    if (lastEvt[watch]) {
      if (now - lastEvt[watch] < 2000) {
        return;
      }
    }
    lastEvt[watch] = now;

    // Handle new files. Re-watch parent directory.
    /*if (evt === 'rename' &! watch.match(fileExtensionPattern)) {
      findAllWatchFiles(watch, watchGivenFile);
    }*/

    if (counter === -1) {
      timer = setTimeout(stopCrashing, 400);
    }
    counter ++;

    var child = exports.child;
    var extension = getExtension(watch);
    sys.debug("detected change at "+watch+" - ext:"+extension);
    if ("coffee" === extension) {
      sys.debug("compiling with coffeescript.");
      exec("coffee -m -c "+watch,function(err, stderr, stdout) {
            if (err) sys.debug(err);
            if (stderr) sys.debug(stderr);
            if (stdout) sys.debug(stdout);
      });
      // The JS file update should cause a restart, so don't do it here.
      /*if (programExt === "coffee") {
        // Don't restart for client side updates.
        if (program !== NO_PROGRAM && watch.indexOf('public/') === -1) process.kill(child.pid);
      }*/
    } else if (extension === "styl") {
      sys.debug('compiling with stylus.');
      exec("stylus "+watch,function(err, stderr, stdout) {
            if (err) sys.debug(err);
            if (stderr) sys.debug(stderr);
            if (stdout) sys.debug(stdout);
      });
    } else if (extension === "eco") {
      sys.debug('compiling with eco.');
      exec("eco -o "+p.dirname(watch)+" "+watch,function(err, stderr, stdout) {
            if (err) sys.debug(err);
            if (stderr) sys.debug(stderr);
            if (stdout) sys.debug(stdout);
      });
    } else if (extension === "jade") {
      if (watch.indexOf("client") > -1) {
        sys.debug('compiling with clientjade wrapper.');
        exec("clientjade.py " + p.dirname(watch) + " ./public",function(err, stderr, stdout) {
              if (err) sys.debug(err);
              if (stderr) sys.debug(stderr);
              if (stdout) sys.debug(stdout);
        });
      }
    } else if (extension === "js" && programExt === "coffee") {
      // Do nothing. TODO: why is this here.
    } else if (extension === "js" && watch.indexOf("public") !== -1) {
      // JS updates in the client folder don't trigger a restart.
    } else {

      if (program !== NO_PROGRAM) process.kill(child.pid);
    }
  });
}

var findAllWatchFiles = function(path, callback) {
  fs.stat(path, function(err, stats){
    if (err) {
      sys.error('Error retrieving stats for file: ' + path);
    } else {
      if (stats.isDirectory()) {
        //callback(p.normalize(path));
        fs.readdir(path, function(err, fileNames) {
          if(err) {
            sys.puts('Error reading path: ' + path);
          }
          else {
            fileNames.forEach(function (fileName) {
              if ( fileName.charAt(0) !== '.'
//                && fileName !== 'node_modules'
                && fileName !== 'components'
                && fileName !== 'bower_components'
                && fileName !== 'run'
                )
                findAllWatchFiles(path + '/' + fileName, callback);
            });
          }
        });
      } else {

        if (path.match(fileExtensionPattern)) {
          callback(p.normalize(path));
        }
      }
    }
  });
}
<|endoftext|>


<commit_before>$.cssHooks.backgroundColor = {
    get: function(elem) {
        if (elem.currentStyle)
            var bg = elem.currentStyle["backgroundColor"];
        else if (window.getComputedStyle)
            var bg = document.defaultView.getComputedStyle(elem,
                null).getPropertyValue("background-color");
        if (bg.search("rgb") == -1)
            return bg;
        else {
            bg = bg.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
            function hex(x) {
                return ("0" + parseInt(x).toString(16)).slice(-2);
            }
            return "#" + hex(bg[1]) + hex(bg[2]) + hex(bg[3]);
        }
    }
};

$.fn.dataTableExt.oSort['numeric_ignore_nan-asc']  = function(x,y) {
    if (isNaN(x) && isNaN(y)) return ((x < y) ? 1 : ((x > y) ?  -1 : 0));

    if (isNaN(x)) return 1;
    if (isNaN(y)) return -1;

    x = parseFloat( x );
    y = parseFloat( y );
    return ((x < y) ? -1 : ((x > y) ?  1 : 0));
};

$.fn.dataTableExt.oSort['numeric_ignore_nan-desc'] = function(x,y) {
    if (isNaN(x) && isNaN(y)) return ((x < y) ? 1 : ((x > y) ?  -1 : 0));

    if (isNaN(x)) return 1;
    if (isNaN(y)) return -1;

    x = parseFloat( x );
    y = parseFloat( y );
    return ((x < y) ?  1 : ((x > y) ? -1 : 0));
};

$.fn.dataTableExt.afnFiltering.push(
    function(oSettings, aData, iDataIndex) {
        var selected_tags = $('.filter_labels h3 span.tag-checked').map(function(k, v) {
                return $(this).text();
            }).get(),
            row_tags = aData[9].split(',');

        if (!selected_tags.length) { // nothing to filter out
            return true;
        } else {
            if (!row_tags.length || (row_tags.length === 1 && row_tags[0] === "")) {
                return false;
            }
            for (var i = 0; i < selected_tags.length; i++) {
                for (var j = 0; j < row_tags.length; j++) {
                    if (selected_tags[i] === row_tags[j]) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
);

$.fn.dataTableExt.afnFiltering.push(
    function(oSettings, aData, iDataIndex) {
        var selected_categories = $('.category_labels h2 span.tag-checked').map(function(k, v) {
                return $(this).css('background-color');
            }).get(),
            row_color = aData[10];
        if (!selected_categories.length) { // nothing to filter out
            return true;
        } else {
            for (var i = 0; i < selected_categories.length; i++) {
                if (selected_categories[i] === row_color) {
                    return true;
                }
            }
        }
        return false;
    }
);

var genomeData = $('#genomeData');
var reset_checkboxes = function(checkbox_settings) {
    var checkboxes = $(".checkbox-row input");
    checkbox_settings.forEach(function(element, index) {
        var checkbox = $(checkboxes[index]);
        checkbox.prop('checked', element).trigger('change');
    });

};
$(document).ready(function() {
    var genome_url = genomeData.data('genome_url');
    var genomeTable = genomeData.dataTable({
        "ajax": genome_url,
        "columns": [
            {"data": "rsid" },
            {"data": "chromosome_position" },
            {"data": "risk_allele" },
            {"data": "genotype" },
            {"data": "disease_trait" },
            {"data": "p_value" },
            {"data": "or_or_beta" },
            {"data": "risk" },
            {"data": "priority", "defaultContent": "0" },
            {"data": "tags", "defaultContent": " "},
            {"data": "color", "defaultContent": ""}
        ],
        "pageLength": 100,
        "aoColumnDefs": [
            { "sType": "numeric_ignore_nan", "aTargets": [ 5, 6 ] },
            { "bSearchable": false, "bVisible": false, "aTargets": [ 8 ] }
        ],
        "columnDefs": [{"targets": [ 8 ], "visible": false, "searchable": false}],
        "order": [[ 8, "desc" ]],
        "processing": true,
        "rowCallback": function(row, data, index) {
            var $row = $(row);
            $row.data('url', encodeURI(data['link'] + '?allele=' + data['genotype']));
            $('td', row).prepend(' ');
        },
        "drawCallback": function( settings ) {
            var rows = $('#genomeData tbody tr');

            // Remove existing event handlers;
            rows.off('click');

            rows.click(function(e) {
                e.preventDefault();
                var row = $(this);
                $.get(row.data('url'), {'ajax':'1'})
                .then(function() {
                    $('#genomeDataDestination').text('Loading...');
                })
                .fail(function(data) {
                    $('#genomeDataDestination').text('error\n'+data.statusCode()+' '+data.statusText+'\n\n'+data.responseText);
                })
                .done(function(data) {
                    $('#genomeDataDestination').html(data);
                });
                return false;
                window.open(row.data('url'), 'Your genome', "height=" + window.screen.height +",width=" + window.screen.width);
            });
            // Fix datatable for fluid container
            genomeData.css('width', '');

            // Ugly way to make table columns show/hide on init as requested
            var checkbox_settings = [
                false, // RSID
                false, // CHROMOSOME POS
                false, // RISK ALLELE
                true, // GENOTYPE
                true, // DISEASE TRAIT
                false, // P VALUE
                false, // OR
                false, // RISK
                false, // PRIORITY
                false, // TAGS
                false  // CATEGORY COLOR
            ];
            $('.table-settings').data('default-values', checkbox_settings);
            reset_checkboxes($('.table-settings').data('default-values'));

        }
    }).columnFilter({ sPlaceHolder: "head:after",
        aoColumns: [
            { type: "number-range" },
            { type: "number-range" },
            { type: "select" },
            { type: "select" },
            { type: "select" },
            { type: "number-range" },
            { type: "number-range" },
            { type: "select" },
            { type: "number-range" },
            { type: "select" },
            { type: "select" },
            { type: "select" }
        ]
    });
});

var progressbar = $('.progress-bar');
var interval;

function updateBar(values) {
    var l = values.received;
    var tot = values.size;

    var perc = (l / tot) * (100.00);
    progressbar.css('width', perc + '%');
    progressbar.text(perc + '%');
    if (values.status === 'done') {
        window.clearInterval(interval);
    }
}

$("form#upload_form").submit(function(e){
    $('form#upload_form input[type=submit]').hide();
    progressbar.parent().show();
    var getProgress = function() {
        $.ajax({
            url: "/progress",
            headers: {"X-Progress-ID": $('#progress-bar').data('upload_id')},
            dataType: 'json',
            success: function(data) {
                updateBar(data);
            }
        });
    };
    interval = window.setInterval(getProgress, 1000);
});

$('.genomeData_advanced').click(function(e) {
    $('#genomeData thead tr.filter-visiblity, .dataTables_length, .dataTables_filter, .table-settings').toggle();
});

$(".checkbox-row input").change(function() {
    var checked = $(this).is(":checked");
    var index = $(this).parent().parent().index();
    $('#genomeData tbody tr').each(function() {
        var $cell = $(this).find("td").eq(index);
        if(checked) {
            $cell.show();
        } else {
            $cell.hide();
        }
        $('td.first', this).removeClass('first');
        $('td:visible:first', this).addClass('first');
    });
    $('#genomeData thead tr').each(function() {
        if(checked) {
            $(this).find("th").eq(index).show();
        } else {
            $(this).find("th").eq(index).hide();
        }
    });
    $('#genomeData tfoot tr').each(function() {
        if(checked) {
            $(this).find("th").eq(index).show();
        } else {
            $(this).find("th").eq(index).hide();
        }
    });
});
$(".table-settings .defaultbutton").click(function() {
    reset_checkboxes($('.table-settings').data('default-values'));
    return false;
});

$('.filter_labels h3 span.label').on('click', function(e) {
    var label = $(e.delegateTarget),
        labelColorOff = label.data('color-off'),
        labelColorOn = label.data('color-on');
    label.toggleClass('tag-checked');
    if (label.hasClass('tag-checked')) {
        label.css('background-color', labelColorOn);
    } else {
        label.css('background-color', labelColorOff);
    }
    genomeData.DataTable().draw();
});

$('.category_labels h2 span.label').on('click', function(e) {
    var category = $(e.delegateTarget);
    category.toggleClass('tag-checked');
    genomeData.DataTable().draw();
});

/**
 * Layout expand
 */
function setLayout() {
    if(window.localStorage['expand'] == 'true') {
        $('.layout').removeClass('container container-fluid').addClass('container-fluid')
        $('[data-toggle=layout-fluid] .glyphicon.glyphicon-resize-full').removeClass('glyphicon-resize-full').addClass('glyphicon-resize-small')
    } else {
        $('.layout').removeClass('container container-fluid').addClass('container')
        $('[data-toggle=layout-fluid] .glyphicon.glyphicon-resize-small').removeClass('glyphicon-resize-small').addClass('glyphicon-resize-full')
    }
}

//setLayout();

$('[data-toggle=layout-fluid]').click(function() {
    window.localStorage['expand'] = String(!(window.localStorage['expand'] == 'true'));
    setLayout();
    return false;
});

if (window.location.href === '/disease/browse/') {
    (function poll(){
        setTimeout(function(){
            if ($('.alert.alert-info').length) {
                location.reload();
                poll();
            }
        }, 1000);
    })();
}

<commit_msg>Tabelka z prawej<commit_after>$.cssHooks.backgroundColor = {
    get: function(elem) {
        if (elem.currentStyle)
            var bg = elem.currentStyle["backgroundColor"];
        else if (window.getComputedStyle)
            var bg = document.defaultView.getComputedStyle(elem,
                null).getPropertyValue("background-color");
        if (bg.search("rgb") == -1)
            return bg;
        else {
            bg = bg.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
            function hex(x) {
                return ("0" + parseInt(x).toString(16)).slice(-2);
            }
            return "#" + hex(bg[1]) + hex(bg[2]) + hex(bg[3]);
        }
    }
};

$.fn.dataTableExt.oSort['numeric_ignore_nan-asc']  = function(x,y) {
    if (isNaN(x) && isNaN(y)) return ((x < y) ? 1 : ((x > y) ?  -1 : 0));

    if (isNaN(x)) return 1;
    if (isNaN(y)) return -1;

    x = parseFloat( x );
    y = parseFloat( y );
    return ((x < y) ? -1 : ((x > y) ?  1 : 0));
};

$.fn.dataTableExt.oSort['numeric_ignore_nan-desc'] = function(x,y) {
    if (isNaN(x) && isNaN(y)) return ((x < y) ? 1 : ((x > y) ?  -1 : 0));

    if (isNaN(x)) return 1;
    if (isNaN(y)) return -1;

    x = parseFloat( x );
    y = parseFloat( y );
    return ((x < y) ?  1 : ((x > y) ? -1 : 0));
};

$.fn.dataTableExt.afnFiltering.push(
    function(oSettings, aData, iDataIndex) {
        var selected_tags = $('.filter_labels h3 span.tag-checked').map(function(k, v) {
                return $(this).text();
            }).get(),
            row_tags = aData[9].split(',');

        if (!selected_tags.length) { // nothing to filter out
            return true;
        } else {
            if (!row_tags.length || (row_tags.length === 1 && row_tags[0] === "")) {
                return false;
            }
            for (var i = 0; i < selected_tags.length; i++) {
                for (var j = 0; j < row_tags.length; j++) {
                    if (selected_tags[i] === row_tags[j]) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
);

$.fn.dataTableExt.afnFiltering.push(
    function(oSettings, aData, iDataIndex) {
        var selected_categories = $('.category_labels h2 span.tag-checked').map(function(k, v) {
                return $(this).css('background-color');
            }).get(),
            row_color = aData[10];
        if (!selected_categories.length) { // nothing to filter out
            return true;
        } else {
            for (var i = 0; i < selected_categories.length; i++) {
                if (selected_categories[i] === row_color) {
                    return true;
                }
            }
        }
        return false;
    }
);

var genomeData = $('#genomeData');
var reset_checkboxes = function(checkbox_settings) {
    var checkboxes = $(".checkbox-row input");
    checkbox_settings.forEach(function(element, index) {
        var checkbox = $(checkboxes[index]);
        checkbox.prop('checked', element).trigger('change');
    });

};
$(document).ready(function() {
    var genome_url = genomeData.data('genome_url');
    var genomeTable = genomeData.dataTable({
        "ajax": genome_url,
        "columns": [
            {"data": "rsid" },
            {"data": "chromosome_position" },
            {"data": "risk_allele" },
            {"data": "genotype" },
            {"data": "disease_trait" },
            {"data": "p_value" },
            {"data": "or_or_beta" },
            {"data": "risk" },
            {"data": "priority", "defaultContent": "0" },
            {"data": "tags", "defaultContent": " "},
            {"data": "color", "defaultContent": ""}
        ],
        "pageLength": 100,
        "aoColumnDefs": [
            { "sType": "numeric_ignore_nan", "aTargets": [ 5, 6 ] },
            { "bSearchable": false, "bVisible": false, "aTargets": [ 8 ] }
        ],
        "columnDefs": [{"targets": [ 8 ], "visible": false, "searchable": false}],
        "order": [[ 8, "desc" ]],
        "processing": true,
        "rowCallback": function(row, data, index) {
            var $row = $(row);
            $row.data('url', encodeURI(data['link'] + '?allele=' + data['genotype']));
            $('td', row).prepend(' ');
        },
        "drawCallback": function( settings ) {
            var rows = $('#genomeData tbody tr');

            // Remove existing event handlers;
            rows.off('click');

            rows.click(function(e) {
                e.preventDefault();
                var row = $(this);
                $('#genomeDataDestination').text('Loading...');
                $.get(row.data('url'), {'ajax':'1'})
                .fail(function(data) {
                    $('#genomeDataDestination').text('error\n'+data.statusCode()+' '+data.statusText+'\n\n'+data.responseText);
                })
                .done(function(data) {
                    $('#genomeDataDestination').html(data);
                });
                return false;
                window.open(row.data('url'), 'Your genome', "height=" + window.screen.height +",width=" + window.screen.width);
            });
            // Fix datatable for fluid container
            genomeData.css('width', '');

            // Ugly way to make table columns show/hide on init as requested
            var checkbox_settings = [
                false, // RSID
                false, // CHROMOSOME POS
                false, // RISK ALLELE
                true, // GENOTYPE
                true, // DISEASE TRAIT
                false, // P VALUE
                false, // OR
                false, // RISK
                false, // PRIORITY
                false, // TAGS
                false  // CATEGORY COLOR
            ];
            $('.table-settings').data('default-values', checkbox_settings);
            reset_checkboxes($('.table-settings').data('default-values'));

        }
    }).columnFilter({ sPlaceHolder: "head:after",
        aoColumns: [
            { type: "number-range" },
            { type: "number-range" },
            { type: "select" },
            { type: "select" },
            { type: "select" },
            { type: "number-range" },
            { type: "number-range" },
            { type: "select" },
            { type: "number-range" },
            { type: "select" },
            { type: "select" },
            { type: "select" }
        ]
    });
});

var progressbar = $('.progress-bar');
var interval;

function updateBar(values) {
    var l = values.received;
    var tot = values.size;

    var perc = (l / tot) * (100.00);
    progressbar.css('width', perc + '%');
    progressbar.text(perc + '%');
    if (values.status === 'done') {
        window.clearInterval(interval);
    }
}

$("form#upload_form").submit(function(e){
    $('form#upload_form input[type=submit]').hide();
    progressbar.parent().show();
    var getProgress = function() {
        $.ajax({
            url: "/progress",
            headers: {"X-Progress-ID": $('#progress-bar').data('upload_id')},
            dataType: 'json',
            success: function(data) {
                updateBar(data);
            }
        });
    };
    interval = window.setInterval(getProgress, 1000);
});

$('.genomeData_advanced').click(function(e) {
    $('#genomeData thead tr.filter-visiblity, .dataTables_length, .dataTables_filter, .table-settings').toggle();
});

$(".checkbox-row input").change(function() {
    var checked = $(this).is(":checked");
    var index = $(this).parent().parent().index();
    $('#genomeData tbody tr').each(function() {
        var $cell = $(this).find("td").eq(index);
        if(checked) {
            $cell.show();
        } else {
            $cell.hide();
        }
        $('td.first', this).removeClass('first');
        $('td:visible:first', this).addClass('first');
    });
    $('#genomeData thead tr').each(function() {
        if(checked) {
            $(this).find("th").eq(index).show();
        } else {
            $(this).find("th").eq(index).hide();
        }
    });
    $('#genomeData tfoot tr').each(function() {
        if(checked) {
            $(this).find("th").eq(index).show();
        } else {
            $(this).find("th").eq(index).hide();
        }
    });
});
$(".table-settings .defaultbutton").click(function() {
    reset_checkboxes($('.table-settings').data('default-values'));
    return false;
});

$('.filter_labels h3 span.label').on('click', function(e) {
    var label = $(e.delegateTarget),
        labelColorOff = label.data('color-off'),
        labelColorOn = label.data('color-on');
    label.toggleClass('tag-checked');
    if (label.hasClass('tag-checked')) {
        label.css('background-color', labelColorOn);
    } else {
        label.css('background-color', labelColorOff);
    }
    genomeData.DataTable().draw();
});

$('.category_labels h2 span.label').on('click', function(e) {
    var category = $(e.delegateTarget);
    category.toggleClass('tag-checked');
    genomeData.DataTable().draw();
});

/**
 * Layout expand
 */
function setLayout() {
    if(window.localStorage['expand'] == 'true') {
        $('.layout').removeClass('container container-fluid').addClass('container-fluid')
        $('[data-toggle=layout-fluid] .glyphicon.glyphicon-resize-full').removeClass('glyphicon-resize-full').addClass('glyphicon-resize-small')
    } else {
        $('.layout').removeClass('container container-fluid').addClass('container')
        $('[data-toggle=layout-fluid] .glyphicon.glyphicon-resize-small').removeClass('glyphicon-resize-small').addClass('glyphicon-resize-full')
    }
}

//setLayout();

$('[data-toggle=layout-fluid]').click(function() {
    window.localStorage['expand'] = String(!(window.localStorage['expand'] == 'true'));
    setLayout();
    return false;
});

if (window.location.href === '/disease/browse/') {
    (function poll(){
        setTimeout(function(){
            if ($('.alert.alert-info').length) {
                location.reload();
                poll();
            }
        }, 1000);
    })();
}

<|endoftext|>


<commit_before>/*
 * service.js: Service model
 *
 * (C) 2013 Rackspace, Ken Perkins
 * MIT LICENSE
 *
 */

// TODO node.js doesn't always gracefully handle exceptions, so we may need
// TODO revisit how we expose invalid input errors

var _ = require('underscore');

/**
 * Service class
 *
 * @description The service class is a thin wrapper on an entry in the openstack
 * service catalog
 *
 * @param {String}  region      the default region to use for this service
 * @param {object}  details     the data for the new service
 * @param {object}  details.endpoints       the array of endpoints
 * @param {String}  details.name            the name of the service
 * @param {String}  details.type            the type of the new service
 * @constructor
 */
var Service = function (region, details) {
  var self = this;

  region = region || '';

  if (!details) {
    throw new Error('details are a required argument');
  }

  self.endpoints = details.endpoints;
  self.name = details.name;
  self.type = details.type;

  self.selectedEndpoint = exports.validateRegionForService(self, region);

  if (!self.selectedEndpoint) {
    throw new Error('Unable to find endpoint for specified region');
  }
};

/**
 * Service.getEndpointUrl
 *
 * @description gets the endpoint URL for a given service, optionally providing
 * the region.
 *
 * @param {object} options              the options for the endpoint call
 * @param {String} [options.region]     a region to use, if provided
 * @param {boolean} [options.internal]  prefer an internal endpoint, if available
 *
 * @returns {String}            the endpoint uri
 */
Service.prototype.getEndpointUrl = function (options) {
  var self = this,
    url = null;

  options = options || {};

  if (options.region) {
    _.each(self.endpoints, function (endpoint) {
      if (!endpoint.region || !matchRegion(endpoint.region, options.region)) {
        return;
      }

      url = getUrl(endpoint);
    });
  }
  else {
    url = getUrl(self.selectedEndpoint);
  }

  /**
   * getUrl
   *
   * @description utility function for getEndpointUrl
   * @param {object} endpoint     the endpoint to use
   * @param {string} [endpoint.internalURL]     the internal URL of the endpoint
   * @param {string} [endpoint.publicURL]       the public URL of the endpoint
   *
   * @returns {String} the uri of the endpoint
   */
  function getUrl(endpoint) {
    return options.internal && endpoint.internalURL
      ? endpoint.internalURL
      : endpoint.publicURL;
  }

  if (!url) {
    throw new Error('Unable to identity endpoint url');
  }

  return url;
};

exports.Service = Service;

/**
 * service.validateRegionForService
 *
 * @description validates that a provided region has an endpoint within a defined
 * service.
 * @param {object}      service     raw service data to validate
 * @param {String}      region      the region to check for
 * @param {Function}    [callback]  optional callback for async validation
 *
 * @returns {object}    The valid endpoint, if found
 */
exports.validateRegionForService = function (service, region, callback) {
  if (!service) {
    var error = new Error('service is a required argument');
    if (callback) {
      return callback(error);
    }

    throw error;
  }

  var validEndpoint;

  // first look for the endpoint that matches the region provided
  _.each(service.endpoints, function (endpoint) {
    if (matchRegion(endpoint.region, region)) {
      validEndpoint = endpoint;
    }
  });

  // if we didn't find a match, but there's only 1 endpoint with no region attribute
  // go ahead and use that one
  if (!validEndpoint && service.endpoints.length === 1 && !service.endpoints[0].region) {
    validEndpoint = service.endpoints[0];
  }

  // if we didn't find an endpoint, error out
  if (!validEndpoint && region) {
    callback && callback(new Error('Unable to identify target endpoint for Service: ' + service.name));
  }
  else if (!validEndpoint) {
    callback && callback(new Error('Unable to identify regionless endpoint for Service: ' + service.name));
  }
  else {
    callback && callback(null, validEndpoint);
  }

  return validEndpoint;
};

function matchRegion(a, b) {
  if (!a && !b) {
    return true;
  }
  else if ((!a && b) || (a && !b)) {
    return false;
  }

  return a.toLowerCase() === b.toLowerCase();
}
<commit_msg>[dist] Dont be as strict about regions.<commit_after>/*
 * service.js: Service model
 *
 * (C) 2013 Rackspace, Ken Perkins
 * MIT LICENSE
 *
 */

// TODO node.js doesn't always gracefully handle exceptions, so we may need
// TODO revisit how we expose invalid input errors

var _ = require('underscore');

/**
 * Service class
 *
 * @description The service class is a thin wrapper on an entry in the openstack
 * service catalog
 *
 * @param {String}  region      the default region to use for this service
 * @param {object}  details     the data for the new service
 * @param {object}  details.endpoints       the array of endpoints
 * @param {String}  details.name            the name of the service
 * @param {String}  details.type            the type of the new service
 * @constructor
 */
var Service = function (region, details) {
  var self = this;

  region = region || '';

  if (!details) {
    throw new Error('details are a required argument');
  }

  self.endpoints = details.endpoints;
  self.name = details.name;
  self.type = details.type;

  self.selectedEndpoint = exports.validateRegionForService(self, region);

  if (!self.selectedEndpoint) {
    throw new Error('Unable to find endpoint for specified region');
  }
};

/**
 * Service.getEndpointUrl
 *
 * @description gets the endpoint URL for a given service, optionally providing
 * the region.
 *
 * @param {object} options              the options for the endpoint call
 * @param {String} [options.region]     a region to use, if provided
 * @param {boolean} [options.internal]  prefer an internal endpoint, if available
 *
 * @returns {String}            the endpoint uri
 */
Service.prototype.getEndpointUrl = function (options) {
  var self = this,
    url = null;

  options = options || {};

  if (options.region) {
    _.each(self.endpoints, function (endpoint) {
      if (!endpoint.region || !matchRegion(endpoint.region, options.region)) {
        return;
      }

      url = getUrl(endpoint);
    });
  }
  else {
    url = getUrl(self.selectedEndpoint);
  }

  /**
   * getUrl
   *
   * @description utility function for getEndpointUrl
   * @param {object} endpoint     the endpoint to use
   * @param {string} [endpoint.internalURL]     the internal URL of the endpoint
   * @param {string} [endpoint.publicURL]       the public URL of the endpoint
   *
   * @returns {String} the uri of the endpoint
   */
  function getUrl(endpoint) {
    return options.internal && endpoint.internalURL
      ? endpoint.internalURL
      : endpoint.publicURL;
  }

  if (!url) {
    throw new Error('Unable to identity endpoint url');
  }

  return url;
};

exports.Service = Service;

/**
 * service.validateRegionForService
 *
 * @description validates that a provided region has an endpoint within a defined
 * service.
 * @param {object}      service     raw service data to validate
 * @param {String}      region      the region to check for
 * @param {Function}    [callback]  optional callback for async validation
 *
 * @returns {object}    The valid endpoint, if found
 */
exports.validateRegionForService = function (service, region, callback) {
  if (!service) {
    var error = new Error('service is a required argument');
    if (callback) {
      return callback(error);
    }

    throw error;
  }

  var validEndpoint;

  // first look for the endpoint that matches the region provided
  _.each(service.endpoints, function (endpoint) {
    if (matchRegion(endpoint.region, region)) {
      validEndpoint = endpoint;
    }
  });

  // if we didn't find a match, but there's only 1 endpoint with no region attribute
  // go ahead and use that one
  if (!validEndpoint && service.endpoints.length === 1) {
    validEndpoint = service.endpoints[0];
  }

  // if we didn't find an endpoint, error out
  if (!validEndpoint && region) {
    callback && callback(new Error('Unable to identify target endpoint for Service: ' + service.name));
  }
  else if (!validEndpoint) {
    callback && callback(new Error('Unable to identify regionless endpoint for Service: ' + service.name));
  }
  else {
    callback && callback(null, validEndpoint);
  }

  return validEndpoint;
};

function matchRegion(a, b) {
  if (!a && !b) {
    return true;
  }
  else if ((!a && b) || (a && !b)) {
    return false;
  }

  return a.toLowerCase() === b.toLowerCase();
}
<|endoftext|>


<commit_before>/*
Copyright 2017 New Vector Ltd

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.
*/

/*
Listens for incoming postMessage requests from embedded widgets. The following API is exposed:
{
    api: "widget",
    action: "content_loaded",
    // additional request fields
    widgetId: $WIDGET_ID
}

The complete request object is returned to the caller with an additional "response" key like so:
{
    api: "widget",
    action: "content_loaded",
    // additional request fields
    widgetId: $WIDGET_ID
    response: { ... }
}

The "api" field is required to use this API, and must be set to "widget" in all requests.

The "action" determines the format of the request and response. All actions can return an error response.

A success response is an object with zero or more keys.

An error response is a "response" object which consists of a sole "error" key to indicate an error.
They look like:
{
    error: {
        message: "Unable to invite user into room.",
        _error: <Original Error Object>
    }
}
The "message" key should be a human-friendly string.

ACTIONS
=======
** All actions must include an "api" field with valie "widget".**
All actions can return an error response instead of the response outlined below.

content_loaded
--------------
Indicates that widget contet has fully loaded

Request:
 - widgetId is the unique ID of the widget instance in riot / matrix state.
 - No additional fields.
Response:
{
    success: true
}
Example:
{
    api: "widget",
    action: "content_loaded",
    widgetId: $WIDGET_ID
}

api_version
-----------
Get the current version of the widget postMessage API

Request:
 - No additional fields.
Response:
{
    api_version: "0.0.1"
}
Example:
{
    api: "widget",
    action: "api_version",
}

supported_api_versions
----------------------
Get versions of the widget postMessage API that are currently supported

Request:
 - No additional fields.
Response:
{
    api: "widget"
    supported_versions: ["0.0.1"]
}
Example:
{
    api: "widget",
    action: "supported_api_versions",
}

*/

const WIDGET_API_VERSION = '0.0.1'; // Current API version
const SUPPORTED_WIDGET_API_VERSIONS = [
    '0.0.1',
];

import dis from './dispatcher';

let listenerCount = 0;
let messageEndpoints = [];

/**
 * Handle widget postMessage events
 * @param  {Event} event Event to handle
 * @return {undefined}
 */
function onMessage(event) {
    if (!event.origin) { // Handle chrome
        event.origin = event.originalEvent.origin;
    }

    // Event origin is empty string if undefined
    if (
        event.origin.length === 0 ||
        trustedEndpoint(event.origin) ||
        event.data.api !== "widget" ||
        !event.data.widgetId
    ) {
        return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise
    }

    const action = event.data.action;
    const widgetId = event.data.widgetId;
    if (action == 'content_loaded') {
        dis.dispatch({
            action: 'widget_content_loaded',
            widgetId: widgetId,
        });
        sendResponse(event, {success: true});
    } else if (action == 'supported_api_versions') {
        sendResponse(event, {
            api: "widget",
            supported_versions: SUPPORTED_WIDGET_API_VERSIONS,
        });
    } else if (action == 'api_version') {
        sendResponse(event, {
            api: "widget",
            version: WIDGET_API_VERSION,
        });
    } else {
        console.warn("Widget postMessage event unhandled");
        sendError(event, {message: "The postMessage was unhandled"});
    }
}

/**
 * Check if message origin is registered as trusted
 * @param  {string} origin PostMessage origin to check
 * @return {boolean}       True if trusted
 */
function trustedEndpoint(origin) {
    if (origin) {
        if (messageEndpoints.filter(function(endpoint) {
            if (endpoint.endpointUrl == origin) {
                return true;
            }
        }).length > 0) {
            return true;
        }
    }

    return false;
}

/**
 * Send a postmessage response to a postMessage request
 * @param  {Event} event  The original postMessage request event
 * @param  {Object} res   Response data
 */
function sendResponse(event, res) {
    const data = JSON.parse(JSON.stringify(event.data));
    data.response = res;
    event.source.postMessage(data, event.origin);
}

/**
 * Send an error response to a postMessage request
 * @param  {Event} event        The original postMessage request event
 * @param  {string} msg         Error message
 * @param  {Error} nestedError  Nested error event (optional)
 */
function sendError(event, msg, nestedError) {
    console.error("Action:" + event.data.action + " failed with message: " + msg);
    const data = JSON.parse(JSON.stringify(event.data));
    data.response = {
        error: {
            message: msg,
        },
    };
    if (nestedError) {
        data.response.error._error = nestedError;
    }
    event.source.postMessage(data, event.origin);
}

/**
 * Represents mapping of widget instance to URLs for trusted postMessage communication.
 */
class WidgetMessageEndpoint {
    /**
     * Mapping of widget instance to URL for trusted postMessage communication.
     * @param  {string} widgetId    Unique widget identifier
     * @param  {string} endpointUrl Widget wurl origin.
     */
    constructor(widgetId, endpointUrl) {
        if (!widgetId) {
            throw new Error("No widgetId specified in widgetMessageEndpoint constructor");
        }
        if (!endpointUrl) {
            throw new Error("No endpoint specified in widgetMessageEndpoint constructor");
        }
        this.widgetId = widgetId;
        this.endpointUrl = endpointUrl;
    }
}

module.exports = {
    /**
     * Register widget message event listeners
     */
    startListening() {
        if (listenerCount === 0) {
            window.addEventListener("message", onMessage, false);
        }
        listenerCount += 1;
    },

    /**
     * De-register widget message event listeners
     */
    stopListening() {
        listenerCount -= 1;
        if (listenerCount === 0) {
            window.removeEventListener("message", onMessage);
        }
        if (listenerCount < 0) {
            // Make an error so we get a stack trace
            const e = new Error(
                "WidgetMessaging: mismatched startListening / stopListening detected." +
                " Negative count",
            );
            console.error(e);
        }
    },

    /**
     * Register a widget endpoint for trusted postMessage communication
     * @param {string} widgetId    Unique widget identifier
     * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host)
     */
    addEndpoint(widgetId, endpointUrl) {
        const endpoint = new WidgetMessageEndpoint(widgetId, endpointUrl);
        if (messageEndpoints && messageEndpoints.length > 0) {
            if (messageEndpoints.filter(function(ep) {
                return (ep.widgetId == widgetId && ep.endpointUrl == endpointUrl);
            }).length > 0) {
                // Message endpoint already registered
                return;
            }
            messageEndpoints.push(endpoint);
        }
    },

    /**
     * De-register a widget endpoint from trusted communication sources
     * @param  {string} widgetId Unique widget identifier
     * @param  {string} endpointUrl Widget wurl origin (protocol + (optional port) + host)
     * @return {boolean} True if endpoint was successfully removed
     */
    removeOrigin(widgetId, endpointUrl) {
        if (messageEndpoints && messageEndpoints.length > 0) {
            const length = messageEndpoints.length;
            messageEndpoints = messageEndpoints.filter(function(endpoint) {
                return (endpoint.widgetId != widgetId || endpoint.endpointUrl != endpointUrl);
            });
            return (length > messageEndpoints.length);
        }
        return false;
    },
};
<commit_msg>Use ES6 style exports.<commit_after>/*
Copyright 2017 New Vector Ltd

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.
*/

/*
Listens for incoming postMessage requests from embedded widgets. The following API is exposed:
{
    api: "widget",
    action: "content_loaded",
    // additional request fields
    widgetId: $WIDGET_ID
}

The complete request object is returned to the caller with an additional "response" key like so:
{
    api: "widget",
    action: "content_loaded",
    // additional request fields
    widgetId: $WIDGET_ID
    response: { ... }
}

The "api" field is required to use this API, and must be set to "widget" in all requests.

The "action" determines the format of the request and response. All actions can return an error response.

A success response is an object with zero or more keys.

An error response is a "response" object which consists of a sole "error" key to indicate an error.
They look like:
{
    error: {
        message: "Unable to invite user into room.",
        _error: <Original Error Object>
    }
}
The "message" key should be a human-friendly string.

ACTIONS
=======
** All actions must include an "api" field with valie "widget".**
All actions can return an error response instead of the response outlined below.

content_loaded
--------------
Indicates that widget contet has fully loaded

Request:
 - widgetId is the unique ID of the widget instance in riot / matrix state.
 - No additional fields.
Response:
{
    success: true
}
Example:
{
    api: "widget",
    action: "content_loaded",
    widgetId: $WIDGET_ID
}

api_version
-----------
Get the current version of the widget postMessage API

Request:
 - No additional fields.
Response:
{
    api_version: "0.0.1"
}
Example:
{
    api: "widget",
    action: "api_version",
}

supported_api_versions
----------------------
Get versions of the widget postMessage API that are currently supported

Request:
 - No additional fields.
Response:
{
    api: "widget"
    supported_versions: ["0.0.1"]
}
Example:
{
    api: "widget",
    action: "supported_api_versions",
}

*/

const WIDGET_API_VERSION = '0.0.1'; // Current API version
const SUPPORTED_WIDGET_API_VERSIONS = [
    '0.0.1',
];

import dis from './dispatcher';

let listenerCount = 0;
let messageEndpoints = [];

/**
 * Register widget message event listeners
 */
function startListening() {
    if (listenerCount === 0) {
        window.addEventListener("message", onMessage, false);
    }
    listenerCount += 1;
}

/**
 * De-register widget message event listeners
 */
function stopListening() {
    listenerCount -= 1;
    if (listenerCount === 0) {
        window.removeEventListener("message", onMessage);
    }
    if (listenerCount < 0) {
        // Make an error so we get a stack trace
        const e = new Error(
            "WidgetMessaging: mismatched startListening / stopListening detected." +
            " Negative count",
        );
        console.error(e);
    }
}

/**
 * Register a widget endpoint for trusted postMessage communication
 * @param {string} widgetId    Unique widget identifier
 * @param {string} endpointUrl Widget wurl origin (protocol + (optional port) + host)
 */
function addEndpoint(widgetId, endpointUrl) {
    const endpoint = new WidgetMessageEndpoint(widgetId, endpointUrl);
    if (messageEndpoints && messageEndpoints.length > 0) {
        if (messageEndpoints.filter(function(ep) {
            return (ep.widgetId == widgetId && ep.endpointUrl == endpointUrl);
        }).length > 0) {
            // Message endpoint already registered
            return;
        }
        messageEndpoints.push(endpoint);
    }
}

/**
 * De-register a widget endpoint from trusted communication sources
 * @param  {string} widgetId Unique widget identifier
 * @param  {string} endpointUrl Widget wurl origin (protocol + (optional port) + host)
 * @return {boolean} True if endpoint was successfully removed
 */
function removeEndpoint(widgetId, endpointUrl) {
    if (messageEndpoints && messageEndpoints.length > 0) {
        const length = messageEndpoints.length;
        messageEndpoints = messageEndpoints.filter(function(endpoint) {
            return (endpoint.widgetId != widgetId || endpoint.endpointUrl != endpointUrl);
        });
        return (length > messageEndpoints.length);
    }
    return false;
}

/**
 * Handle widget postMessage events
 * @param  {Event} event Event to handle
 * @return {undefined}
 */
function onMessage(event) {
    if (!event.origin) { // Handle chrome
        event.origin = event.originalEvent.origin;
    }

    // Event origin is empty string if undefined
    if (
        event.origin.length === 0 ||
        trustedEndpoint(event.origin) ||
        event.data.api !== "widget" ||
        !event.data.widgetId
    ) {
        return; // don't log this - debugging APIs like to spam postMessage which floods the log otherwise
    }

    const action = event.data.action;
    const widgetId = event.data.widgetId;
    if (action == 'content_loaded') {
        dis.dispatch({
            action: 'widget_content_loaded',
            widgetId: widgetId,
        });
        sendResponse(event, {success: true});
    } else if (action == 'supported_api_versions') {
        sendResponse(event, {
            api: "widget",
            supported_versions: SUPPORTED_WIDGET_API_VERSIONS,
        });
    } else if (action == 'api_version') {
        sendResponse(event, {
            api: "widget",
            version: WIDGET_API_VERSION,
        });
    } else {
        console.warn("Widget postMessage event unhandled");
        sendError(event, {message: "The postMessage was unhandled"});
    }
}

/**
 * Check if message origin is registered as trusted
 * @param  {string} origin PostMessage origin to check
 * @return {boolean}       True if trusted
 */
function trustedEndpoint(origin) {
    if (origin) {
        if (messageEndpoints.filter(function(endpoint) {
            if (endpoint.endpointUrl == origin) {
                return true;
            }
        }).length > 0) {
            return true;
        }
    }

    return false;
}

/**
 * Send a postmessage response to a postMessage request
 * @param  {Event} event  The original postMessage request event
 * @param  {Object} res   Response data
 */
function sendResponse(event, res) {
    const data = JSON.parse(JSON.stringify(event.data));
    data.response = res;
    event.source.postMessage(data, event.origin);
}

/**
 * Send an error response to a postMessage request
 * @param  {Event} event        The original postMessage request event
 * @param  {string} msg         Error message
 * @param  {Error} nestedError  Nested error event (optional)
 */
function sendError(event, msg, nestedError) {
    console.error("Action:" + event.data.action + " failed with message: " + msg);
    const data = JSON.parse(JSON.stringify(event.data));
    data.response = {
        error: {
            message: msg,
        },
    };
    if (nestedError) {
        data.response.error._error = nestedError;
    }
    event.source.postMessage(data, event.origin);
}

/**
 * Represents mapping of widget instance to URLs for trusted postMessage communication.
 */
class WidgetMessageEndpoint {
    /**
     * Mapping of widget instance to URL for trusted postMessage communication.
     * @param  {string} widgetId    Unique widget identifier
     * @param  {string} endpointUrl Widget wurl origin.
     */
    constructor(widgetId, endpointUrl) {
        if (!widgetId) {
            throw new Error("No widgetId specified in widgetMessageEndpoint constructor");
        }
        if (!endpointUrl) {
            throw new Error("No endpoint specified in widgetMessageEndpoint constructor");
        }
        this.widgetId = widgetId;
        this.endpointUrl = endpointUrl;
    }
}

export default {
    startListening: startListening,
    stopListening: stopListening,
    addEndpoint: addEndpoint,
    removeEndpoint: removeEndpoint,
};
<|endoftext|>


<commit_before>// @flow

import React, { Component } from 'react'
import { Button, Grid, Row, Col } from 'react-bootstrap'
import {Link} from 'react-router'
import {LinkContainer} from 'react-router-bootstrap'

import { DEFAULT_DESCRIPTION, DEFAULT_LOGO, DEFAULT_TITLE } from '../../common/constants'
import { getConfigProperty, isModuleEnabled } from '../../common/util/config'
import PublicPage from './PublicPage'

import type {Props as ContainerProps} from '../containers/ActivePublicLandingPage'
import type {ManagerUserState} from '../../types/reducers'

type Props = ContainerProps & {
  user: ManagerUserState
}

export default class PublicLandingPage extends Component<Props> {
  render () {
    const appTitle = getConfigProperty('application.title') || DEFAULT_TITLE
    const appDescription = getConfigProperty('application.description') || DEFAULT_DESCRIPTION
    const logoLarge = getConfigProperty('application.logo_large') || DEFAULT_LOGO
    return (
      <PublicPage ref='publicPage'>
        <Grid>
          <Row>
            <Col style={{textAlign: 'center'}} smOffset={4} xs={12} sm={4}>

{appTitle}

            </Col>
          </Row>
          <Row>
            <Col style={{textAlign: 'center', marginTop: '15px'}} smOffset={4} xs={12} sm={4}>

                {this.props.user.profile
                  ? <LinkContainer to='/home'>
                    <Button bsSize='large'>
                      View dashboard
                    </Button>
                  </LinkContainer>
                  :
                    {appDescription}

                }

              {!isModuleEnabled('enterprise') &&

                Learn more about Data Tools{' '}
                here.

}

                {!this.props.user.profile
                  ? Existing users <Link to='/login'>sign in here</Link>.
                  : null
                }

            </Col>
          </Row>
        </Grid>

                ©
              {' '}
              IBI Group

      </PublicPage>
    )
  }
}
<commit_msg>refactor(branding): fix IBI url<commit_after>// @flow

import React, { Component } from 'react'
import { Button, Grid, Row, Col } from 'react-bootstrap'
import {Link} from 'react-router'
import {LinkContainer} from 'react-router-bootstrap'

import { DEFAULT_DESCRIPTION, DEFAULT_LOGO, DEFAULT_TITLE } from '../../common/constants'
import { getConfigProperty, isModuleEnabled } from '../../common/util/config'
import PublicPage from './PublicPage'

import type {Props as ContainerProps} from '../containers/ActivePublicLandingPage'
import type {ManagerUserState} from '../../types/reducers'

type Props = ContainerProps & {
  user: ManagerUserState
}

export default class PublicLandingPage extends Component<Props> {
  render () {
    const appTitle = getConfigProperty('application.title') || DEFAULT_TITLE
    const appDescription = getConfigProperty('application.description') || DEFAULT_DESCRIPTION
    const logoLarge = getConfigProperty('application.logo_large') || DEFAULT_LOGO
    return (
      <PublicPage ref='publicPage'>
        <Grid>
          <Row>
            <Col style={{textAlign: 'center'}} smOffset={4} xs={12} sm={4}>

{appTitle}

            </Col>
          </Row>
          <Row>
            <Col style={{textAlign: 'center', marginTop: '15px'}} smOffset={4} xs={12} sm={4}>

                {this.props.user.profile
                  ? <LinkContainer to='/home'>
                    <Button bsSize='large'>
                      View dashboard
                    </Button>
                  </LinkContainer>
                  :
                    {appDescription}

                }

              {!isModuleEnabled('enterprise') &&

                Learn more about Data Tools{' '}
                here.

}

                {!this.props.user.profile
                  ? Existing users <Link to='/login'>sign in here</Link>.
                  : null
                }

            </Col>
          </Row>
        </Grid>

                ©
              {' '}
              IBI Group

      </PublicPage>
    )
  }
}
<|endoftext|>


<commit_before>const config = require('../../../knexfile').intweb
const knex = require('knex')(config)
const dateFormatter = require('../date-formatter')
const claimDecisionEnum = require('../../constants/claim-decision-enum')
const tasksEnum = require('../../constants/tasks-enum')
const paymentMethodEnum = require('../../constants/payment-method-enum')
const insertClaimEvent = require('./insert-claim-event')
const insertTaskSendClaimNotification = require('./insert-task-send-claim-notification')
const updateRelatedClaimRemainingOverpaymentAmount = require('./update-related-claims-remaining-overpayment-amount')
const log = require('../log')

module.exports = function (claimId, claimDecision) {
  return knex('Claim').where('ClaimId', claimId)
    .join('Eligibility', 'Claim.EligibilityId', '=', 'Eligibility.EligibilityId')
    .first('Eligibility.EligibilityId', 'Eligibility.Reference')
    .then(function (result) {
      var eligibilityId = result.EligibilityId
      var reference = result.Reference
      var caseworker = claimDecision.caseworker
      var decision = claimDecision.decision
      var note = claimDecision.note
      var nomisCheck = claimDecision.nomisCheck
      var releaseDateIsSet = claimDecision.releaseDateIsSet
      var releaseDate = null
      if (claimDecision.releaseDateIsSet) {
        releaseDate = claimDecision.releaseDate.toDate()
      }
      var dwpCheck = claimDecision.dwpCheck
      var visitConfirmationCheck = claimDecision.visitConfirmationCheck
      var rejectionReasonId = claimDecision.rejectionReasonId
      var allExpensesManuallyProcessed = areAllExpensesManuallyProcessed(claimDecision.claimExpenseResponses)
      var expiryDate = claimDecision.expiryDate.toDate()

      return Promise.all([updateEligibility(eligibilityId, decision),
        updateClaim(claimId, caseworker, decision, note, visitConfirmationCheck, allExpensesManuallyProcessed, rejectionReasonId),
        updateVisitor(eligibilityId, dwpCheck, expiryDate),
        updatePrisoner(eligibilityId, nomisCheck, releaseDateIsSet, releaseDate),
        updateClaimExpenses(claimDecision.claimExpenseResponses),
        insertClaimEventForDecision(reference, eligibilityId, claimId, decision, note, caseworker),
        updateRemainingOverpaymentAmounts(claimId, reference, decision),
        sendClaimNotification(reference, eligibilityId, claimId, decision)])
    })
}

function updateEligibility (eligibilityId, decision) {
  return knex('Eligibility').where('EligibilityId', eligibilityId).update('Status', decision)
}

function updateClaim (claimId, caseworker, decision, note, visitConfirmationCheck, allExpensesManuallyProcessed, rejectionReasonId) {
  var updateObject = {}
  if (decision === claimDecisionEnum.APPROVED) {
    updateObject = {
      Caseworker: caseworker,
      Status: decision,
      Note: note,
      VisitConfirmationCheck: visitConfirmationCheck,
      DateReviewed: dateFormatter.now().toDate(),
      AssignedTo: null, // clear assignment
      AssignmentExpiry: null,
      LastUpdated: dateFormatter.now().toDate(),
      DateApproved: dateFormatter.now().toDate()
    }
  } else if (decision === claimDecisionEnum.REJECTED || decision === claimDecisionEnum.REQUEST_INFORMATION) {
    updateObject = {
      Caseworker: caseworker,
      Status: decision,
      Note: note,
      VisitConfirmationCheck: visitConfirmationCheck,
      DateReviewed: dateFormatter.now().toDate(),
      AssignedTo: null, // clear assignment
      AssignmentExpiry: null,
      LastUpdated: dateFormatter.now().toDate(),
      DateApproved: null,
      RejectionReasonId: rejectionReasonId
    }
  } else {
    updateObject = {
      Caseworker: caseworker,
      Status: decision,
      Note: note,
      VisitConfirmationCheck: visitConfirmationCheck,
      DateReviewed: dateFormatter.now().toDate(),
      AssignedTo: null, // clear assignment
      AssignmentExpiry: null,
      LastUpdated: dateFormatter.now().toDate()
    }
  }

  if (updateObject.Note.length > 250) {
    updateObject.Note = updateObject.Note.substring(0, 250)
  }

  if (allExpensesManuallyProcessed) {
    updateObject.PaymentMethod = paymentMethodEnum.MANUALLY_PROCESSED.value
  }

  return knex('Claim').where('ClaimId', claimId).update(updateObject).then(
    log.info('Claim ID ' + claimId + ' Closed with Status: ' + updateObject.Status)
  )
}

function updateVisitor (eligibilityId, dwpCheck, expiryDate) {
  return knex('Visitor').where('EligibilityId', eligibilityId).update({
    DWPCheck: dwpCheck,
    BenefitExpiryDate: expiryDate
  })
}

function updatePrisoner (eligibilityId, nomisCheck, releaseDateIsSet, releaseDate) {
  return knex('Prisoner').where('EligibilityId', eligibilityId).update({
    NomisCheck: nomisCheck,
    ReleaseDateIsSet: releaseDateIsSet,
    ReleaseDate: releaseDate
  })
}

function updateClaimExpenses (claimExpenseResponses) {
  var updates = []
  if (claimExpenseResponses) {
    claimExpenseResponses.forEach(function (claimExpenseResponse) {
      updates.push(updateClaimExpense(claimExpenseResponse))
    })
  }
  return Promise.all(updates)
}

function updateClaimExpense (claimExpenseResponse) {
  return knex('ClaimExpense').where('ClaimExpenseId', claimExpenseResponse.claimExpenseId).update({
    ApprovedCost: claimExpenseResponse.approvedCost,
    Status: claimExpenseResponse.status
  })
}

function insertClaimEventForDecision (reference, eligibilityId, claimId, decision, note, caseworker) {
  const event = `CLAIM-${decision}`
  return insertClaimEvent(reference, eligibilityId, claimId, event, null, note, caseworker, false)
}

function updateRemainingOverpaymentAmounts (claimId, reference, decision) {
  if (decision === claimDecisionEnum.APPROVED) {
    return updateRelatedClaimRemainingOverpaymentAmount(claimId, reference)
  } else {
    return Promise.resolve(null)
  }
}

function sendClaimNotification (reference, eligibilityId, claimId, decision) {
  var notificationType
  if (decision === claimDecisionEnum.APPROVED) {
    notificationType = tasksEnum.ACCEPT_CLAIM_NOTIFICATION
  } else if (decision === claimDecisionEnum.REJECTED) {
    notificationType = tasksEnum.REJECT_CLAIM_NOTIFICATION
  } else if (decision === claimDecisionEnum.REQUEST_INFORMATION) {
    notificationType = tasksEnum.REQUEST_INFORMATION_CLAIM_NOTIFICATION
  }

  return insertTaskSendClaimNotification(notificationType, reference, eligibilityId, claimId)
}

function areAllExpensesManuallyProcessed (claimExpenseResponses) {
  var result = true

  claimExpenseResponses.forEach(function (claimExpenseResponse) {
    if (claimExpenseResponse.status !== claimDecisionEnum.MANUALLY_PROCESSED) {
      result = false
    }
  })

  return result
}
<commit_msg>APVS0230: Changing the formatting of expiry date and release date as toDate() has caused issues<commit_after>const config = require('../../../knexfile').intweb
const knex = require('knex')(config)
const dateFormatter = require('../date-formatter')
const claimDecisionEnum = require('../../constants/claim-decision-enum')
const tasksEnum = require('../../constants/tasks-enum')
const paymentMethodEnum = require('../../constants/payment-method-enum')
const insertClaimEvent = require('./insert-claim-event')
const insertTaskSendClaimNotification = require('./insert-task-send-claim-notification')
const updateRelatedClaimRemainingOverpaymentAmount = require('./update-related-claims-remaining-overpayment-amount')
const log = require('../log')

module.exports = function (claimId, claimDecision) {
  return knex('Claim').where('ClaimId', claimId)
    .join('Eligibility', 'Claim.EligibilityId', '=', 'Eligibility.EligibilityId')
    .first('Eligibility.EligibilityId', 'Eligibility.Reference')
    .then(function (result) {
      var eligibilityId = result.EligibilityId
      var reference = result.Reference
      var caseworker = claimDecision.caseworker
      var decision = claimDecision.decision
      var note = claimDecision.note
      var nomisCheck = claimDecision.nomisCheck
      var releaseDateIsSet = claimDecision.releaseDateIsSet
      var releaseDate = null
      if (claimDecision.releaseDateIsSet) {
        releaseDate = claimDecision.releaseDate.format('YYYY-MM-DD')
      }
      var dwpCheck = claimDecision.dwpCheck
      var visitConfirmationCheck = claimDecision.visitConfirmationCheck
      var rejectionReasonId = claimDecision.rejectionReasonId
      var allExpensesManuallyProcessed = areAllExpensesManuallyProcessed(claimDecision.claimExpenseResponses)
      var expiryDate = claimDecision.expiryDate.format('YYYY-MM-DD')

      return Promise.all([updateEligibility(eligibilityId, decision),
        updateClaim(claimId, caseworker, decision, note, visitConfirmationCheck, allExpensesManuallyProcessed, rejectionReasonId),
        updateVisitor(eligibilityId, dwpCheck, expiryDate),
        updatePrisoner(eligibilityId, nomisCheck, releaseDateIsSet, releaseDate),
        updateClaimExpenses(claimDecision.claimExpenseResponses),
        insertClaimEventForDecision(reference, eligibilityId, claimId, decision, note, caseworker),
        updateRemainingOverpaymentAmounts(claimId, reference, decision),
        sendClaimNotification(reference, eligibilityId, claimId, decision)])
    })
}

function updateEligibility (eligibilityId, decision) {
  return knex('Eligibility').where('EligibilityId', eligibilityId).update('Status', decision)
}

function updateClaim (claimId, caseworker, decision, note, visitConfirmationCheck, allExpensesManuallyProcessed, rejectionReasonId) {
  var updateObject = {}
  if (decision === claimDecisionEnum.APPROVED) {
    updateObject = {
      Caseworker: caseworker,
      Status: decision,
      Note: note,
      VisitConfirmationCheck: visitConfirmationCheck,
      DateReviewed: dateFormatter.now().toDate(),
      AssignedTo: null, // clear assignment
      AssignmentExpiry: null,
      LastUpdated: dateFormatter.now().toDate(),
      DateApproved: dateFormatter.now().toDate()
    }
  } else if (decision === claimDecisionEnum.REJECTED || decision === claimDecisionEnum.REQUEST_INFORMATION) {
    updateObject = {
      Caseworker: caseworker,
      Status: decision,
      Note: note,
      VisitConfirmationCheck: visitConfirmationCheck,
      DateReviewed: dateFormatter.now().toDate(),
      AssignedTo: null, // clear assignment
      AssignmentExpiry: null,
      LastUpdated: dateFormatter.now().toDate(),
      DateApproved: null,
      RejectionReasonId: rejectionReasonId
    }
  } else {
    updateObject = {
      Caseworker: caseworker,
      Status: decision,
      Note: note,
      VisitConfirmationCheck: visitConfirmationCheck,
      DateReviewed: dateFormatter.now().toDate(),
      AssignedTo: null, // clear assignment
      AssignmentExpiry: null,
      LastUpdated: dateFormatter.now().toDate()
    }
  }

  if (updateObject.Note.length > 250) {
    updateObject.Note = updateObject.Note.substring(0, 250)
  }

  if (allExpensesManuallyProcessed) {
    updateObject.PaymentMethod = paymentMethodEnum.MANUALLY_PROCESSED.value
  }

  return knex('Claim').where('ClaimId', claimId).update(updateObject).then(
    log.info('Claim ID ' + claimId + ' Closed with Status: ' + updateObject.Status)
  )
}

function updateVisitor (eligibilityId, dwpCheck, expiryDate) {
  return knex('Visitor').where('EligibilityId', eligibilityId).update({
    DWPCheck: dwpCheck,
    BenefitExpiryDate: expiryDate
  })
}

function updatePrisoner (eligibilityId, nomisCheck, releaseDateIsSet, releaseDate) {
  return knex('Prisoner').where('EligibilityId', eligibilityId).update({
    NomisCheck: nomisCheck,
    ReleaseDateIsSet: releaseDateIsSet,
    ReleaseDate: releaseDate
  })
}

function updateClaimExpenses (claimExpenseResponses) {
  var updates = []
  if (claimExpenseResponses) {
    claimExpenseResponses.forEach(function (claimExpenseResponse) {
      updates.push(updateClaimExpense(claimExpenseResponse))
    })
  }
  return Promise.all(updates)
}

function updateClaimExpense (claimExpenseResponse) {
  return knex('ClaimExpense').where('ClaimExpenseId', claimExpenseResponse.claimExpenseId).update({
    ApprovedCost: claimExpenseResponse.approvedCost,
    Status: claimExpenseResponse.status
  })
}

function insertClaimEventForDecision (reference, eligibilityId, claimId, decision, note, caseworker) {
  const event = `CLAIM-${decision}`
  return insertClaimEvent(reference, eligibilityId, claimId, event, null, note, caseworker, false)
}

function updateRemainingOverpaymentAmounts (claimId, reference, decision) {
  if (decision === claimDecisionEnum.APPROVED) {
    return updateRelatedClaimRemainingOverpaymentAmount(claimId, reference)
  } else {
    return Promise.resolve(null)
  }
}

function sendClaimNotification (reference, eligibilityId, claimId, decision) {
  var notificationType
  if (decision === claimDecisionEnum.APPROVED) {
    notificationType = tasksEnum.ACCEPT_CLAIM_NOTIFICATION
  } else if (decision === claimDecisionEnum.REJECTED) {
    notificationType = tasksEnum.REJECT_CLAIM_NOTIFICATION
  } else if (decision === claimDecisionEnum.REQUEST_INFORMATION) {
    notificationType = tasksEnum.REQUEST_INFORMATION_CLAIM_NOTIFICATION
  }

  return insertTaskSendClaimNotification(notificationType, reference, eligibilityId, claimId)
}

function areAllExpensesManuallyProcessed (claimExpenseResponses) {
  var result = true

  claimExpenseResponses.forEach(function (claimExpenseResponse) {
    if (claimExpenseResponse.status !== claimDecisionEnum.MANUALLY_PROCESSED) {
      result = false
    }
  })

  return result
}
<|endoftext|>