<commit_before>import classNames from "classnames";
import { Dropdown, Table, Tooltip } from "reactjs-components";
import { injectIntl } from "react-intl";
import { Link, routerShape } from "react-router";
import React, { PropTypes } from "react";

import Icon from "#SRC/js/components/Icon";
import Links from "#SRC/js/constants/Links";
import NestedServiceLinks from "#SRC/js/components/NestedServiceLinks";
import ResourceTableUtil from "#SRC/js/utils/ResourceTableUtil";
import StringUtil from "#SRC/js/utils/StringUtil";
import TableUtil from "#SRC/js/utils/TableUtil";
import Units from "#SRC/js/utils/Units";
import { isSDKService } from "#SRC/js/utils/ServiceUtil";

import HealthBar from "../../components/HealthBar";
import Pod from "../../structs/Pod";
import Service from "../../structs/Service";
import ServiceActionDisabledModal
  from "../../components/modals/ServiceActionDisabledModal";
import {
  DELETE,
  EDIT,
  MORE,
  OPEN,
  RESTART,
  RESUME,
  SCALE,
  SUSPEND
} from "../../constants/ServiceActionItem";
import ServiceActionLabels from "../../constants/ServiceActionLabels";
import ServiceStatusTypes from "../../constants/ServiceStatusTypes";
import ServiceStatusWarning from "../../components/ServiceStatusWarning";
import ServiceTableHeaderLabels from "../../constants/ServiceTableHeaderLabels";
import ServiceTableUtil from "../../utils/ServiceTableUtil";
import ServiceTree from "../../structs/ServiceTree";

const StatusMapping = {
  Running: "running-state"
};

const columnClasses = {
  name: "service-table-column-name",
  status: "service-table-column-status",
  cpus: "service-table-column-cpus",
  mem: "service-table-column-mem",
  disk: "service-table-column-disk",
  actions: "service-table-column-actions"
};

const METHODS_TO_BIND = [
  "onActionsItemSelection",
  "handleServiceAction",
  "handleActionDisabledModalOpen",
  "handleActionDisabledModalClose",
  "renderHeadline",
  "renderStats",
  "renderStatus",
  "renderServiceActions"
];

class ServicesTable extends React.Component {
  constructor() {
    super(...arguments);

    this.state = { actionDisabledService: null };

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

  onActionsItemSelection(service, actionItem) {
    const isGroup = service instanceof ServiceTree;
    let containsSDKService = false;

    if (isGroup) {
      containsSDKService =
        // #findItem will flatten the service tree
        service.findItem(function(item) {
          return item instanceof Service && isSDKService(item);
        }) != null;
    }

    if (
      // We still want to support the `open` action to display the web view
      actionItem.id !== OPEN &&
      (containsSDKService || isSDKService(service))
    ) {
      this.handleActionDisabledModalOpen(service, actionItem.id);
    } else {
      this.handleServiceAction(service, actionItem.id);
    }
  }

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

    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(actionDisabledService, actionDisabledID) {
    this.setState({ actionDisabledService, actionDisabledID });
  }

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

  getOpenInNewWindowLink(service) {
    // This might be a serviceTree and therefore we need this check
    // And getWebURL might therefore not be available
    if (!this.hasWebUI(service)) {
      return null;
    }

    return (

        <Icon
          color="neutral"
          className="icon-margin-left"
          id="open-external"
          size="mini"
        />

    );
  }

  getServiceLink(service) {
    const id = encodeURIComponent(service.getId());
    const isGroup = service instanceof ServiceTree;
    const serviceLink = isGroup
      ? `/services/overview/${id}`
      : `/services/detail/${id}`;

    if (this.props.isFiltered) {
      return (
        <NestedServiceLinks
          serviceID={id}
          className="service-breadcrumb"
          majorLinkClassName="service-breadcrumb-service-id"
          minorLinkWrapperClassName="service-breadcrumb-crumb"
        />
      );
    }

    return (
      <Link className="table-cell-link-primary text-overflow" to={serviceLink}>
        {service.getName()}
      </Link>
    );
  }

  getImage(service) {
    if (service instanceof ServiceTree) {
      // Get serviceTree image/icon
      return (
        <Icon
          className="icon-margin-right"
          color="grey"
          id="folder"
          size="mini"
        />
      );
    }

    // Get service image/icon
    return (

    );
  }

  hasWebUI(service) {
    return (
      service instanceof Service &&
      service.getWebURL() != null &&
      service.getWebURL() !== ""
    );
  }

  renderHeadline(prop, service) {
    const id = encodeURIComponent(service.getId());
    const isGroup = service instanceof ServiceTree;
    const serviceLink = isGroup
      ? `/services/overview/${id}`
      : `/services/detail/${id}`;

    return (

        <Link className="table-cell-icon" to={serviceLink}>
          {this.getImage(service)}
        </Link>

          {this.getServiceLink(service)}
          {this.getOpenInNewWindowLink(service)}

    );
  }

  renderServiceActions(prop, service) {
    const isGroup = service instanceof ServiceTree;
    const isPod = service instanceof Pod;
    const isSingleInstanceApp = service.getLabels()
      .MARATHON_SINGLE_INSTANCE_APP;
    const instancesCount = service.getInstancesCount();
    const scaleTextID = isGroup
      ? ServiceActionLabels.scale_by
      : ServiceActionLabels[SCALE];
    const restartObj = {
      className: classNames({
        hidden: isPod || isGroup || instancesCount === 0
      }),
      id: RESTART,
      html: this.props.intl.formatMessage({
        id: ServiceActionLabels[RESTART]
      })
    };
    const isSDK = isSDKService(service) ? [] : [restartObj];

    const dropdownItems = [
      {
        className: "hidden",
        id: MORE,
        html: "",
        selectedHtml: <Icon id="ellipsis-vertical" size="mini" />
      },
      {
        className: classNames({
          hidden: !this.hasWebUI(service)
        }),
        id: OPEN,
        html: this.props.intl.formatMessage({ id: ServiceActionLabels.open })
      },
      {
        className: classNames({ hidden: isGroup }),
        id: EDIT,
        html: this.props.intl.formatMessage({ id: ServiceActionLabels.edit })
      },
      {
        className: classNames({
          hidden: (isGroup && instancesCount === 0) || isSingleInstanceApp
        }),
        id: SCALE,
        html: this.props.intl.formatMessage({ id: scaleTextID })
      }
    ].concat(isSDK, [
      {
        className: classNames({
          hidden: instancesCount === 0
        }),
        id: SUSPEND,
        html: this.props.intl.formatMessage({
          id: ServiceActionLabels[SUSPEND]
        })
      },
      {
        className: classNames({
          hidden: isGroup || instancesCount > 0
        }),
        id: RESUME,
        html: this.props.intl.formatMessage({
          id: ServiceActionLabels[RESUME]
        })
      },
      {
        id: DELETE,
        html: (

            {this.props.intl.formatMessage({
              id: ServiceActionLabels[DELETE]
            })}

        )
      }
    ]);

    return (
      <Tooltip content="More actions">
        <Dropdown
          anchorRight={true}
          buttonClassName="button button-mini button-link"
          dropdownMenuClassName="dropdown-menu"
          dropdownMenuListClassName="dropdown-menu-list"
          dropdownMenuListItemClassName="clickable"
          wrapperClassName="dropdown flush-bottom table-cell-icon"
          items={dropdownItems}
          persistentID={MORE}
          onItemSelection={this.onActionsItemSelection.bind(this, service)}
          scrollContainer=".gm-scroll-view"
          scrollContainerParentSelector=".gm-prevented"
          title="More actions"
          transition={true}
          transitionName="dropdown-menu"
        />
      </Tooltip>
    );
  }

  renderStatus(prop, service) {
    const instancesCount = service.getInstancesCount();
    const serviceId = service.getId();
    const serviceStatusText = service.getStatus();
    const serviceStatusClassSet = StatusMapping[serviceStatusText] || "";
    const { key: serviceStatusKey } = service.getServiceStatus();
    const tasksSummary = service.getTasksSummary();
    const tasksRunning = service.getTaskCount();
    const isDeploying =
      serviceStatusKey === ServiceStatusTypes.WAITING ||
      serviceStatusKey === ServiceStatusTypes.DEPLOYING;

    const conciseOverview = tasksRunning === instancesCount
      ? ` (${tasksRunning})`
      : ` (${tasksRunning}/${instancesCount})`;

    const verboseOverview = tasksRunning === instancesCount
      ? ` (${tasksRunning} ${StringUtil.pluralize("Instance", tasksRunning)})`
      : ` (${tasksRunning} of ${instancesCount} Instances)`;

    return (

          <HealthBar
            isDeploying={isDeploying}
            key={serviceId}
            tasksSummary={tasksSummary}
            instancesCount={instancesCount}
          />

            {serviceStatusText}

          {verboseOverview}
          {conciseOverview}
          <ServiceStatusWarning item={service} />

    );
  }

  renderStats(prop, service) {
    const resource = service.getResources()[prop];

    return (

        {Units.formatResource(prop, resource)}

    );
  }

  getCellClasses(prop, sortBy, row) {
    const isHeader = row == null;

    return classNames(columnClasses[prop], {
      active: prop === sortBy.prop,
      clickable: isHeader
    });
  }

  getColumns() {
    const heading = ResourceTableUtil.renderHeading(ServiceTableHeaderLabels);

    return [
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "name",
        render: this.renderHeadline,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "status",
        helpText: (

            {"At-a-glance overview of the global application or group state. "}

              Read more
            .

        ),
        render: this.renderStatus,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "cpus",
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "mem",
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "disk",
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "actions",
        render: this.renderServiceActions,
        sortable: false,
        heading() {
          return null;
        }
      }
    ];
  }

  getColGroup() {
    return (
      <colgroup>
        <col className={columnClasses.name} />
        <col className={columnClasses.status} />
        <col className={columnClasses.cpus} />
        <col className={columnClasses.mem} />
        <col className={columnClasses.disk} />
        <col className={columnClasses.actions} />
      </colgroup>
    );
  }

  render() {
    const { actionDisabledService, actionDisabledID } = this.state;

    return (

        <ServiceActionDisabledModal
          actionID={actionDisabledID}
          open={actionDisabledService != null}
          onClose={this.handleActionDisabledModalClose}
          service={actionDisabledService}
        />

    );
  }
}

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

ServicesTable.defaultProps = {
  isFiltered: false,
  services: []
};

ServicesTable.propTypes = {
  isFiltered: PropTypes.bool,
  services: PropTypes.array
};

module.exports = injectIntl(ServicesTable);
<commit_msg>fix(PageHeaderActions): refactor ServiceTable to follow ServiceDetail Refactor ServiceTable to follow ServiceDetail pattern when adding the dropdown actions<commit_after>import classNames from "classnames";
import { Dropdown, Table, Tooltip } from "reactjs-components";
import { injectIntl } from "react-intl";
import { Link, routerShape } from "react-router";
import React, { PropTypes } from "react";

import Icon from "#SRC/js/components/Icon";
import Links from "#SRC/js/constants/Links";
import NestedServiceLinks from "#SRC/js/components/NestedServiceLinks";
import ResourceTableUtil from "#SRC/js/utils/ResourceTableUtil";
import StringUtil from "#SRC/js/utils/StringUtil";
import TableUtil from "#SRC/js/utils/TableUtil";
import Units from "#SRC/js/utils/Units";
import { isSDKService } from "#SRC/js/utils/ServiceUtil";

import HealthBar from "../../components/HealthBar";
import Pod from "../../structs/Pod";
import Service from "../../structs/Service";
import ServiceActionDisabledModal
  from "../../components/modals/ServiceActionDisabledModal";
import {
  DELETE,
  EDIT,
  MORE,
  OPEN,
  RESTART,
  RESUME,
  SCALE,
  SUSPEND
} from "../../constants/ServiceActionItem";
import ServiceActionLabels from "../../constants/ServiceActionLabels";
import ServiceStatusTypes from "../../constants/ServiceStatusTypes";
import ServiceStatusWarning from "../../components/ServiceStatusWarning";
import ServiceTableHeaderLabels from "../../constants/ServiceTableHeaderLabels";
import ServiceTableUtil from "../../utils/ServiceTableUtil";
import ServiceTree from "../../structs/ServiceTree";

const StatusMapping = {
  Running: "running-state"
};

const columnClasses = {
  name: "service-table-column-name",
  status: "service-table-column-status",
  cpus: "service-table-column-cpus",
  mem: "service-table-column-mem",
  disk: "service-table-column-disk",
  actions: "service-table-column-actions"
};

const METHODS_TO_BIND = [
  "onActionsItemSelection",
  "handleServiceAction",
  "handleActionDisabledModalOpen",
  "handleActionDisabledModalClose",
  "renderHeadline",
  "renderStats",
  "renderStatus",
  "renderServiceActions"
];

class ServicesTable extends React.Component {
  constructor() {
    super(...arguments);

    this.state = { actionDisabledService: null };

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

  onActionsItemSelection(service, actionItem) {
    const isGroup = service instanceof ServiceTree;
    let containsSDKService = false;

    if (isGroup) {
      containsSDKService =
        // #findItem will flatten the service tree
        service.findItem(function(item) {
          return item instanceof Service && isSDKService(item);
        }) != null;
    }

    if (
      // We still want to support the `open` action to display the web view
      actionItem.id !== OPEN &&
      (containsSDKService || isSDKService(service))
    ) {
      this.handleActionDisabledModalOpen(service, actionItem.id);
    } else {
      this.handleServiceAction(service, actionItem.id);
    }
  }

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

    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(actionDisabledService, actionDisabledID) {
    this.setState({ actionDisabledService, actionDisabledID });
  }

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

  getOpenInNewWindowLink(service) {
    // This might be a serviceTree and therefore we need this check
    // And getWebURL might therefore not be available
    if (!this.hasWebUI(service)) {
      return null;
    }

    return (

        <Icon
          color="neutral"
          className="icon-margin-left"
          id="open-external"
          size="mini"
        />

    );
  }

  getServiceLink(service) {
    const id = encodeURIComponent(service.getId());
    const isGroup = service instanceof ServiceTree;
    const serviceLink = isGroup
      ? `/services/overview/${id}`
      : `/services/detail/${id}`;

    if (this.props.isFiltered) {
      return (
        <NestedServiceLinks
          serviceID={id}
          className="service-breadcrumb"
          majorLinkClassName="service-breadcrumb-service-id"
          minorLinkWrapperClassName="service-breadcrumb-crumb"
        />
      );
    }

    return (
      <Link className="table-cell-link-primary text-overflow" to={serviceLink}>
        {service.getName()}
      </Link>
    );
  }

  getImage(service) {
    if (service instanceof ServiceTree) {
      // Get serviceTree image/icon
      return (
        <Icon
          className="icon-margin-right"
          color="grey"
          id="folder"
          size="mini"
        />
      );
    }

    // Get service image/icon
    return (

    );
  }

  hasWebUI(service) {
    return (
      service instanceof Service &&
      service.getWebURL() != null &&
      service.getWebURL() !== ""
    );
  }

  renderHeadline(prop, service) {
    const id = encodeURIComponent(service.getId());
    const isGroup = service instanceof ServiceTree;
    const serviceLink = isGroup
      ? `/services/overview/${id}`
      : `/services/detail/${id}`;

    return (

        <Link className="table-cell-icon" to={serviceLink}>
          {this.getImage(service)}
        </Link>

          {this.getServiceLink(service)}
          {this.getOpenInNewWindowLink(service)}

    );
  }

  renderServiceActions(prop, service) {
    const isGroup = service instanceof ServiceTree;
    const isPod = service instanceof Pod;
    const isSingleInstanceApp = service.getLabels()
      .MARATHON_SINGLE_INSTANCE_APP;
    const instancesCount = service.getInstancesCount();
    const scaleTextID = isGroup
      ? ServiceActionLabels.scale_by
      : ServiceActionLabels[SCALE];
    const isSDK = isSDKService(service);

    const actions = [];

    actions.push({
      className: "hidden",
      id: MORE,
      html: "",
      selectedHtml: <Icon id="ellipsis-vertical" size="mini" />
    });

    if (this.hasWebUI(service)) {
      actions.push({
        id: OPEN,
        html: this.props.intl.formatMessage({ id: ServiceActionLabels.open })
      });
    }

    if (!isGroup) {
      actions.push({
        id: EDIT,
        html: this.props.intl.formatMessage({ id: ServiceActionLabels.edit })
      });
    }

    if (!isGroup && instancesCount > 0 && !isSingleInstanceApp) {
      actions.push({
        id: SCALE,
        html: this.props.intl.formatMessage({ id: scaleTextID })
      });
    }

    if (!isPod && !isGroup && instancesCount > 0 && !isSDK) {
      actions.push({
        id: RESTART,
        html: this.props.intl.formatMessage({
          id: ServiceActionLabels[RESTART]
        })
      });
    }

    if (instancesCount > 0) {
      actions.push({
        id: SUSPEND,
        html: this.props.intl.formatMessage({
          id: ServiceActionLabels[SUSPEND]
        })
      });
    }

    if (!isGroup && instancesCount === 0) {
      actions.push({
        className: classNames({
          hidden: isGroup || instancesCount > 0
        }),
        id: RESUME,
        html: this.props.intl.formatMessage({
          id: ServiceActionLabels[RESUME]
        })
      });
    }

    actions.push({
      id: DELETE,
      html: (

          {this.props.intl.formatMessage({
            id: ServiceActionLabels[DELETE]
          })}

      )
    });

    return (
      <Tooltip content="More actions">
        <Dropdown
          anchorRight={true}
          buttonClassName="button button-mini button-link"
          dropdownMenuClassName="dropdown-menu"
          dropdownMenuListClassName="dropdown-menu-list"
          dropdownMenuListItemClassName="clickable"
          wrapperClassName="dropdown flush-bottom table-cell-icon"
          items={actions}
          persistentID={MORE}
          onItemSelection={this.onActionsItemSelection.bind(this, service)}
          scrollContainer=".gm-scroll-view"
          scrollContainerParentSelector=".gm-prevented"
          title="More actions"
          transition={true}
          transitionName="dropdown-menu"
        />
      </Tooltip>
    );
  }

  renderStatus(prop, service) {
    const instancesCount = service.getInstancesCount();
    const serviceId = service.getId();
    const serviceStatusText = service.getStatus();
    const serviceStatusClassSet = StatusMapping[serviceStatusText] || "";
    const { key: serviceStatusKey } = service.getServiceStatus();
    const tasksSummary = service.getTasksSummary();
    const tasksRunning = service.getTaskCount();
    const isDeploying =
      serviceStatusKey === ServiceStatusTypes.WAITING ||
      serviceStatusKey === ServiceStatusTypes.DEPLOYING;

    const conciseOverview = tasksRunning === instancesCount
      ? ` (${tasksRunning})`
      : ` (${tasksRunning}/${instancesCount})`;

    const verboseOverview = tasksRunning === instancesCount
      ? ` (${tasksRunning} ${StringUtil.pluralize("Instance", tasksRunning)})`
      : ` (${tasksRunning} of ${instancesCount} Instances)`;

    return (

          <HealthBar
            isDeploying={isDeploying}
            key={serviceId}
            tasksSummary={tasksSummary}
            instancesCount={instancesCount}
          />

            {serviceStatusText}

          {verboseOverview}
          {conciseOverview}
          <ServiceStatusWarning item={service} />

    );
  }

  renderStats(prop, service) {
    const resource = service.getResources()[prop];

    return (

        {Units.formatResource(prop, resource)}

    );
  }

  getCellClasses(prop, sortBy, row) {
    const isHeader = row == null;

    return classNames(columnClasses[prop], {
      active: prop === sortBy.prop,
      clickable: isHeader
    });
  }

  getColumns() {
    const heading = ResourceTableUtil.renderHeading(ServiceTableHeaderLabels);

    return [
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "name",
        render: this.renderHeadline,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "status",
        helpText: (

            {"At-a-glance overview of the global application or group state. "}

              Read more
            .

        ),
        render: this.renderStatus,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "cpus",
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "mem",
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "disk",
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.getCellClasses,
        headerClassName: this.getCellClasses,
        prop: "actions",
        render: this.renderServiceActions,
        sortable: false,
        heading() {
          return null;
        }
      }
    ];
  }

  getColGroup() {
    return (
      <colgroup>
        <col className={columnClasses.name} />
        <col className={columnClasses.status} />
        <col className={columnClasses.cpus} />
        <col className={columnClasses.mem} />
        <col className={columnClasses.disk} />
        <col className={columnClasses.actions} />
      </colgroup>
    );
  }

  render() {
    const { actionDisabledService, actionDisabledID } = this.state;

    return (

        <ServiceActionDisabledModal
          actionID={actionDisabledID}
          open={actionDisabledService != null}
          onClose={this.handleActionDisabledModalClose}
          service={actionDisabledService}
        />

    );
  }
}

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

ServicesTable.defaultProps = {
  isFiltered: false,
  services: []
};

ServicesTable.propTypes = {
  isFiltered: PropTypes.bool,
  services: PropTypes.array
};

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


<commit_before>var fs = require('fs');
var path = require('path');

var nodeSpotifyWebHelper = require('node-spotify-webhelper');
var request = require('request');

var profile = require('windows.system.userprofile');
var storage = require('windows.storage');

var spotify = new nodeSpotifyWebHelper.SpotifyWebHelper();

var lockScreenImageDir = path.join(__dirname, 'lockscreen_img');

// make sure the directory in which we save the images exist
if (!fs.existsSync(lockScreenImageDir)) {
  fs.mkdirSync(lockScreenImageDir);
}

var imageLocation = path.join(lockScreenImageDir, 'image.png');
var defaultImage = path.join(lockscrenImageDir, 'default.png');
var spotifyImage = path.join(lockScreenImageDir, 'spotify.png');
var pausedImage = path.join(lockScreenImageDir, 'paused.png');

function download(uri, filename, callback) {
  callback = callback || function () {};
  var st = request(uri).pipe(fs.createWriteStream(filename));
  st.on('close', callback);
  st.on('error', callback);
};

// sets the windows lockscreen to the current image path, using NodeRT modules
function setLockScreen(path, cb) {
  cb = cb || function() {}
  storage.StorageFile.getFileFromPathAsync(path, function(err, file) {
    if (err) {
      console.error('Error getting image file:', err);
      cb(err);
    }

    profile.LockScreen.setImageFileAsync(file, function(err) {
      if (err) {
        console.error('Error setting lock screen image:', err);
        return cb(err);
      }
      cb();
    });
  });
}

// holds the artistName of the track that is currently playing
var currentArtistName;

// 1. Get the currently playing track information using SpotifyWebHelper
// 2. Check if track.artist_resource.name is different from the value in currentArtistName - if not return
// 3. If it's a new artist:
//    3.1 ??

/* 2. Check if the track that we got is different from the value in currentTrackUri - if not - return
   3. If it's a new track:
      3.1 scrape the track's web page and get the url of the image assocaited with the track
      3.2 download the image and save it to file
      3.3 set the downaloded image as the lockscreen
*/
function setLockScreenIfArtistChanged(cb) {

  var spotify = new nodeSpotifyWebHelper.SpotifyWebHelper();

  cb = cb || function() {};

  spotify.getStatus(function (err, res) {

    if (err) {
      console.info("Error, skipping");
      return cb();
    }

    if (!res || !res.track) {

      if (currentArtistName != "none") {
        console.info('No data, setting default');
        currentArtistName = "none";
        setLockScreen(defaultImage, function(err) {
          return cb();
        });
      }
    }

    else {

      if (res.playing) {

        if (currentArtistName === res.track.artist_resource.name) {
          return cb(null, false);
        }

        currentArtistName = res.track.artist_resource.name;

        var url = "https://api.spotify.com/v1/artists/";

        if (res.track.artist_resource.uri) {
          var url = url + res.track.artist_resource.uri.split(':')[2];
        }

        request(url, function (err, res, body) {

          if (err) {
            console.info('Error');
            return cb();
          }

          if (!body) {
            console.info('No image data, setting default');

            setLockScreen(spotifyImage, function(err) {
              return cb();
            });

          }

          var obj = JSON.parse(body);

          if (!obj.images) {

            console.info('No image data, setting default');

            setLockScreen(spotifyImage, function(err) {
              return cb();
            });
          }

          else {

            try {

              var imageUrl = obj.images[0].url;
              console.info('Setting lockscreen: ' + currentArtistName);

              download(imageUrl, imageLocation, function (err) {

                if (err) {
                  console.info('error, skipping');
                  return cb();
                }

                setLockScreen(imageLocation, function(err) {
                  cb();
                });

              });

            }

            catch (err) {
              console.info('No image data, setting default');
              setLockScreen(spotifyImage, function(err) {
                return cb();
              });

            }

          }

        });
      }

      else {
        if (currentArtistName != "paused") {
          console.info('Spotify is paused, setting default');
          currentArtistName = "paused";

          setLockScreen(pausedImage, function(err) {
            return cb();
          });

        }

      }

    }

  });

};

setInterval(function () {
  setLockScreenIfArtistChanged();
}, 10000);
<commit_msg>Comment changes<commit_after>var fs = require('fs');
var path = require('path');

var nodeSpotifyWebHelper = require('node-spotify-webhelper');
var request = require('request');

var profile = require('windows.system.userprofile');
var storage = require('windows.storage');

var spotify = new nodeSpotifyWebHelper.SpotifyWebHelper();

var lockScreenImageDir = path.join(__dirname, 'lockscreen_img');

// make sure the directory in which we save the images exist
if (!fs.existsSync(lockScreenImageDir)) {
  fs.mkdirSync(lockScreenImageDir);
}

var imageLocation = path.join(lockScreenImageDir, 'image.png');
var defaultImage = path.join(lockscrenImageDir, 'default.png');
var spotifyImage = path.join(lockScreenImageDir, 'spotify.png');
var pausedImage = path.join(lockScreenImageDir, 'paused.png');

function download(uri, filename, callback) {
  callback = callback || function () {};
  var st = request(uri).pipe(fs.createWriteStream(filename));
  st.on('close', callback);
  st.on('error', callback);
};

// sets the windows lockscreen to the current image path, using NodeRT modules
function setLockScreen(path, cb) {
  cb = cb || function() {}
  storage.StorageFile.getFileFromPathAsync(path, function(err, file) {
    if (err) {
      console.error('Error getting image file:', err);
      cb(err);
    }

    profile.LockScreen.setImageFileAsync(file, function(err) {
      if (err) {
        console.error('Error setting lock screen image:', err);
        return cb(err);
      }
      cb();
    });
  });
}

// holds the artistName of the track that is currently playing
var currentArtistName;

// 1. Get the currently playing track information using SpotifyWebHelper
// 2. Check if track.artist_resource.name is different from the value in currentArtistName - if not return
// 3. If it's a new artist:
//    3.1
function setLockScreenIfArtistChanged(cb) {

  var spotify = new nodeSpotifyWebHelper.SpotifyWebHelper();

  cb = cb || function() {};

  spotify.getStatus(function (err, res) {

    if (err) {
      console.info("Error, skipping");
      return cb();
    }

    if (!res || !res.track) {

      if (currentArtistName != "none") {
        console.info('No data, setting default');
        currentArtistName = "none";
        setLockScreen(defaultImage, function(err) {
          return cb();
        });
      }
    }

    else {

      if (res.playing) {

        if (currentArtistName === res.track.artist_resource.name) {
          return cb(null, false);
        }

        currentArtistName = res.track.artist_resource.name;

        var url = "https://api.spotify.com/v1/artists/";

        if (res.track.artist_resource.uri) {
          var url = url + res.track.artist_resource.uri.split(':')[2];
        }

        request(url, function (err, res, body) {

          if (err) {
            console.info('Error');
            return cb();
          }

          if (!body) {
            console.info('No image data, setting default');

            setLockScreen(spotifyImage, function(err) {
              return cb();
            });

          }

          var obj = JSON.parse(body);

          if (!obj.images) {

            console.info('No image data, setting default');

            setLockScreen(spotifyImage, function(err) {
              return cb();
            });
          }

          else {

            try {

              var imageUrl = obj.images[0].url;
              console.info('Setting lockscreen: ' + currentArtistName);

              download(imageUrl, imageLocation, function (err) {

                if (err) {
                  console.info('error, skipping');
                  return cb();
                }

                setLockScreen(imageLocation, function(err) {
                  cb();
                });

              });

            }

            catch (err) {
              console.info('No image data, setting default');
              setLockScreen(spotifyImage, function(err) {
                return cb();
              });

            }

          }

        });
      }

      else {
        if (currentArtistName != "paused") {
          console.info('Spotify is paused, setting default');
          currentArtistName = "paused";

          setLockScreen(pausedImage, function(err) {
            return cb();
          });

        }

      }

    }

  });

};

setInterval(function () {
  setLockScreenIfArtistChanged();
}, 10000);
<|endoftext|>


<commit_before>import CollectionNode from '../nodes/collectionNode.js';
import FieldNode from '../nodes/fieldNode.js';
import dotize from './dotize.js';

const specialFields = ['$filters', '$options', '$metaFilters'];

/**
 * Creates node objects from the body
 * @param root
 */
function createNodes(root) {
    _.each(root.body, (body, fieldName) => {
        if (_.contains(specialFields, fieldName)) {
            return _.extend(root.props, {
                [fieldName]: body
            });
        }

        // checking if it is a link.
        let linker = root.collection.getLinker(fieldName);

        if (linker) {
            let subroot = new CollectionNode(linker.getLinkedCollection(), body, fieldName);
            root.add(subroot);

            return createNodes(subroot);
        }

        // it's not a link and not a special variable => we assume it's a field.
        if (_.isObject(body)) {
            let dotted = dotize.convert({[fieldName]: body});
            _.each(dotted, (value, key) => {
                root.add(new FieldNode(key, value));
            });
        } else {
            let fieldNode = new FieldNode(fieldName, body);
            root.add(fieldNode);
        }
    });
}

export default function (collection, body) {
    let root = new CollectionNode(collection, body);
    createNodes(root);

    return root;
};<commit_msg>added fix to make it pass the tests in phantomjs for travis<commit_after>import CollectionNode from '../nodes/collectionNode.js';
import FieldNode from '../nodes/fieldNode.js';
import dotize from './dotize.js';

const specialFields = ['$filters', '$options', '$metaFilters'];

/**
 * Creates node objects from the body
 * @param root
 */
function createNodes(root) {
    // fix for phantomjs tests
    if (!_.isObject(root.body)) {
        return;
    }

    _.each(root.body, (body, fieldName) => {
        if (_.contains(specialFields, fieldName)) {
            return _.extend(root.props, {
                [fieldName]: body
            });
        }

        // checking if it is a link.
        let linker = root.collection.getLinker(fieldName);

        if (linker) {
            let subroot = new CollectionNode(linker.getLinkedCollection(), body, fieldName);
            root.add(subroot);

            return createNodes(subroot);
        }

        // it's not a link and not a special variable => we assume it's a field.
        if (_.isObject(body)) {
            let dotted = dotize.convert({[fieldName]: body});
            _.each(dotted, (value, key) => {
                root.add(new FieldNode(key, value));
            });
        } else {
            let fieldNode = new FieldNode(fieldName, body);
            root.add(fieldNode);
        }
    });
}

export default function (collection, body) {
    let root = new CollectionNode(collection, body);
    createNodes(root);

    return root;
};<|endoftext|>


<commit_before>({
    baseUrl: 'src',
    out: 'Lacuna-Web-Client-jQuery-Build.js',
    name: 'load',

    shim: {
        jqueryUI: ['jquery'], // Attach jQueryUI to jQuery.
        underscore: {
            exports: '_'
        },
        zebra_cookie: ['jquery'] // Attach zebra_cookie to jQuery.
    },

    paths: {
        jquery: 'js/jquery',
        jqueryUI: 'js/jqueryUI',
        zebra_cookie: 'js/zebra_cookie',
        underscore: 'js/underscore'
    }
})
<commit_msg>Changing how the build process works.<commit_after>({
    baseUrl: 'src',
    out: 'Lacuna-Web-Client-jQuery-Build.js',
    name: 'load',

    keepBuildDir: true,

    shim: {
        jqueryUI: ['jquery'], // Attach jQueryUI to jQuery.
        underscore: {
            exports: '_'
        },
        zebra_cookie: ['jquery'] // Attach zebra_cookie to jQuery.
    },

    paths: {
        jquery: 'js/jquery',
        jqueryUI: 'js/jqueryUI',
        zebra_cookie: 'js/zebra_cookie',
        underscore: 'js/underscore'
    },

    modules: [
        { name: "buildingType/planetaryCommand" },
        { name: "buildingType/shipyard" },
        { name: "buildingType/spaceport" }
    ]
})
<|endoftext|>


<commit_before>/**
 * Used to fetch a Sidekick analyser from a registry and install it.
 * Emits events if downloading [downloading, downloaded, installed]
 */

"use strict";

const proxyAll = require("@sidekick/common/eventHelpers").proxyAll;

const fs = require('fs');
const path = require('path');
const EventEmitter = require('events');
const inherits = require('util').inherits;

const Promise = require('bluebird');
const jsonWithComments = require('strip-json-comments');
const requestCB = require('request');
const semver = require('semver');
const _ = require('lodash');
const debug = require('debug')('analyser-manager');

const npmExtractor = require('./extractors/npmExtractor');
const UnknownAnalyserError = require('./errors/UnknownAnalyserError');

const exists = Promise.promisify(fs.stat);
const canAccess = Promise.promisify(fs.access);
const readFile = Promise.promisify(fs.readFile);
const mkdir = Promise.promisify(fs.mkdir);
const request = Promise.promisify(requestCB);

module.exports = exports = AnalyserManager;

/**
 * Create instance
 * @param analyserInstallLocation where to install the analysers to (absolute path)
 * @constructor
 */
function AnalyserManager(analyserInstallLocation){
  var self = this;

  EventEmitter.call(self);

  self.ANALYSER_INSTALL_DIR = analyserInstallLocation;
  self.ALL_ANALYSERS;

  /**
   * Initialise the all analyser cache, create the analysers dir etc..
   * @returns {bluebird|exports|module.exports}
   */
  self.init = function() {
    return exists(self.ANALYSER_INSTALL_DIR)
      .then(function(){
        debug('install dir exists');
        return canWrite(self.ANALYSER_INSTALL_DIR)
          .then(function(){
            debug('install dir writeable');
            return self.fetchAnalyserList();
          })
        },
        function(){
          debug('install dir does not exists');
          return mkdir(self.ANALYSER_INSTALL_DIR)
            .then(function(){
              debug('install dir now exists');
              return canWrite(self.ANALYSER_INSTALL_DIR)
                .then(function(){
                  debug('install dir now writeable');
                  return self.fetchAnalyserList();
                })
            })
            .catch(function(cantMakeDirErr){
              return doReject(`Unable to create sidekick analyser directory: ${self.ANALYSER_INSTALL_DIR}`, cantMakeDirErr);
            })
        }
      );

    function canWrite(dir){
      return canAccess(dir, fs.W_OK)
        .then(function(){
          return doResolve();
        })
        .catch(function(err){
          return doReject('Unable to write to sidekick analyser directory', err);
        })
    }
  };

  /**
   * Fetch a list of all the analysers that Sidekick supports
   * @returns {bluebird|exports|module.exports}
   */
  self.fetchAnalyserList = function(){
    const SK_CENTRAL_ANALYSER_LIST_URL = 'https://raw.githubusercontent.com/sidekickcode/analysers/master/analysers.json';

    return request(SK_CENTRAL_ANALYSER_LIST_URL)
      .then(function(response) {
        if(response.statusCode == 200) {
          debug('have analysers list');
          self.ALL_ANALYSERS = JSON.parse(jsonWithComments(response.body));
          return doResolve(self.ALL_ANALYSERS);
        } else {
          debug('analyser list unavailable: ' + response.statusCode);
          return doReject('Unable to fetch list of analysers');
        }
      }, function(err){
        debug('error fetching analyser list');
        return doReject('Unable to fetch list of analysers', err);
      })
  };

  /**
   * Fetch the canonical analyser config stored in teh central list of analysers.
   * @param analyserName the name of the analyser to fetch the config for
   * @returns Promise {path: [abs path to analyser], config: [analyser config]}
   */
  self.fetchCanonicalAnalyserConfig = function(analyserName){
    if(!self.ALL_ANALYSERS) {
      return self.fetchAnalyserList()
        .then(function() {
          return returnConfig();
        })
    } else {
      return returnConfig();
    }

    function returnConfig(){
      var analyserConfig = self.ALL_ANALYSERS[analyserName];
      if (analyserConfig) {
        return doResolve(analyserConfig);
      } else {
        return doReject(`Unknown analyser '${analyserName}'`);
      }
    }

  };

  /**
   * Fetch and analyser object to be run (its config and path to its executable).
   * Will install the analyser for a registry if not found on the local install.
   * If no version specified and the analyser does not exist locally, it will install the latest version.
   * @param analyserName the name of the analyser to fetch the config for
   * @param version (optional) the specific version of the analyser to return data for.
   * @returns Promise {path: [abs path to analyser], config: [analyser config]}
   */
  self.fetchAnalyser = function(analyserName, version){
    var pathToAnalyser = path.join(self.ANALYSER_INSTALL_DIR, `${analyserName}@${version}`);

    return exists(pathToAnalyser)
      .then(function(fileStat){
        return readAnalyserConfig(pathToAnalyser)
          .then(function(configObj){
            return doResolve({path: pathToAnalyser, config: configObj});
          });
      }, function(err){
        return doReject(`Unable to fetch config for analyser '${analyserName}'`, err);
      })
  };

  /**
   * Install the analyser from a registry.
   * If the analyser already exists locally (same version) then we just return the config.
   * If no version specified it will install the latest version.
   * @param analyserName the name of the analyser to fetch the config for
   * @param version (optional) the specific version of the analyser to return data for.
   * @returns Promise {path: [abs path to analyser], config: [analyser config]}
   */
  self.installAnalyser = function(analyser){
    var haveVersion;
    if(!analyser.version || analyser.version === 'latest'){
      haveVersion = self.isNewerVersionAvailable(analyser.name);
    } else {
      haveVersion = Promise.resolve({"latest": analyser.version});
    }

    return haveVersion.then(function(version){
      var versionToInstall = version.latest;
      var pathToAnalyser = path.join(self.ANALYSER_INSTALL_DIR, `${analyser.name}@${versionToInstall}`);

      return exists(pathToAnalyser) //checks for @latest as well as specific version
        .then(function(fileStat){
            return readAnalyserConfig(pathToAnalyser)
                .then(function(configObj){
                  return doResolve({path: pathToAnalyser, config: configObj});
                });
            },
            function(err){
              if(err.code === 'ENOENT'){
                //no specific version dir or @latest dir
                return _installAnalyser(analyser, versionToInstall)
                    .then(function(configObj){
                      return doResolve({path: pathToAnalyser, config: configObj});
                    });
              } else {
                return doReject('Cannot read analyser install dir', err);
              }
            }
        )
    });

  };

  /**
   * Get the latest version info for an analyser {newer: [boolean], latest: [string]}
   * @param analyserName
   * @param version
   * @returns {bluebird|exports|module.exports}
   */
  self.isNewerVersionAvailable = function(analyserName, version){
    return getAllAnalyserEntry(analyserName)
      .then(function(analyserConfig){
        var extractor;
        if(analyserConfig.registry === 'npm') {
          extractor = new npmExtractor();
        }
        proxyAll(extractor, self);

        return extractor.getLatestVersion(analyserName)
          .then(function(latestVersion){
            if(semver.valid(version) && semver.valid(latestVersion)){
              return doResolve({"newer" : semver.lt(version, latestVersion), "latest": latestVersion});
            } else {
              if(semver.valid(latestVersion)){
                //we were passed a garbage version - still useful to say what the latest version is
                return doResolve({"latest": latestVersion});
              } else {
                return doReject(`Invalid version '${version}' for analyser '${analyserName}'`);
              }
            }
          })
        })
  };

  /**
   * Validate a list of analysers - removing any unknown analysers
   * @param analysers Array of possible analysers
   * @retuns Array of known analysers
   */
  self.validateAnalyserList = function(analysers){
    var validAnalysers = [];
    debug('analysers: ' + JSON.stringify(analysers));

    return new Promise(function(resolve, reject){
      if(self.ALL_ANALYSERS){
        doResolve();
      } else {
        self.fetchAnalyserList()
          .then(function(ALL_ANALYSER){
            debug('have analyser list: ' + ALL_ANALYSER);
            doResolve();
          });
      }

      function doResolve(){
        _.each(analysers, function(analyser){
          if(self.ALL_ANALYSERS[analyser.name]){
            validAnalysers.push(analyser);
          }
        });
        resolve(validAnalysers);
      }
    });
  };

  /**
   * Read and parse the config for a locally installed analyser
   * @param analyserPath the abs path of the analyser config file
   */
  function readAnalyserConfig(analyserPath) {
    var filePath = path.join(analyserPath, 'config.json');

    return readFile(filePath, {encoding: 'utf8'})
      .then(function(fileContents){
        try {
          return doResolve(JSON.parse(jsonWithComments(fileContents)));
        } catch(err){
          return doReject(`Unable to parse config file for analyser '${analyserPath}'`, err);
        }
      }, function(err){
        return doReject(`Unable to read config file for analyser '${analyserPath}'`, err);
      });
  }

  function _installAnalyser(analyser, version){
    return getAllAnalyserEntry(analyser.name)
      .then(function(analyserConfig){
        var config = analyserConfig.config; //strip the wrapper which includes registry etc..

        if(version !== 'latest' && !semver(version)) {
          return doReject(`Invalid version '${version}' for analyser '${analyser.name}'`);
        }

        var extractor;
        //TODO - support other registries (extractors shoudl have common interface (fetch func and ee)
        if(analyserConfig.registry === 'npm') {
          extractor = new npmExtractor();
        } else {
          return doReject(`Unknown registry '${analyserConfig.registry}'`);
        }
        proxyAll(extractor, self);

        return extractor.fetch(analyser, version, self.ANALYSER_INSTALL_DIR)
          .then(function(){
            return doResolve(config);  //return the newly installed analyser config
          })
      })
  }

  function getAllAnalyserEntry(analyserName){
    return self.fetchAnalyserList()
      .then(function (ALL_ANALYSERS) {
        var analyserConfig = ALL_ANALYSERS[analyserName];
        if (analyserConfig) {
          return doResolve(analyserConfig);
        } else {
          return Promise.reject(new UnknownAnalyserError(analyserName));
        }
      })
  }

  function doResolve(stuff){
    return Promise.resolve(stuff);
  }
  function doReject(errMsg, err){
    if(err && err.message){
      return Promise.reject(Error(`${errMsg}\n${err.message}`, err));
    } else {
      return Promise.reject(Error(errMsg, err));
    }
  }

}

inherits(AnalyserManager, EventEmitter);
<commit_msg>fix: added more debug to fetchAnalyserList<commit_after>/**
 * Used to fetch a Sidekick analyser from a registry and install it.
 * Emits events if downloading [downloading, downloaded, installed]
 */

"use strict";

const proxyAll = require("@sidekick/common/eventHelpers").proxyAll;

const fs = require('fs');
const path = require('path');
const EventEmitter = require('events');
const inherits = require('util').inherits;

const Promise = require('bluebird');
const jsonWithComments = require('strip-json-comments');
const requestCB = require('request');
const semver = require('semver');
const _ = require('lodash');
const debug = require('debug')('analyser-manager');

const npmExtractor = require('./extractors/npmExtractor');
const UnknownAnalyserError = require('./errors/UnknownAnalyserError');

const exists = Promise.promisify(fs.stat);
const canAccess = Promise.promisify(fs.access);
const readFile = Promise.promisify(fs.readFile);
const mkdir = Promise.promisify(fs.mkdir);
const request = Promise.promisify(requestCB);

module.exports = exports = AnalyserManager;

/**
 * Create instance
 * @param analyserInstallLocation where to install the analysers to (absolute path)
 * @constructor
 */
function AnalyserManager(analyserInstallLocation){
  var self = this;

  EventEmitter.call(self);

  self.ANALYSER_INSTALL_DIR = analyserInstallLocation;
  self.ALL_ANALYSERS;

  /**
   * Initialise the all analyser cache, create the analysers dir etc..
   * @returns {bluebird|exports|module.exports}
   */
  self.init = function() {
    return exists(self.ANALYSER_INSTALL_DIR)
      .then(function(){
        debug('install dir exists');
        return canWrite(self.ANALYSER_INSTALL_DIR)
          .then(function(){
            debug('install dir writeable');
            return self.fetchAnalyserList();
          })
        },
        function(){
          debug('install dir does not exists');
          return mkdir(self.ANALYSER_INSTALL_DIR)
            .then(function(){
              debug('install dir now exists');
              return canWrite(self.ANALYSER_INSTALL_DIR)
                .then(function(){
                  debug('install dir now writeable');
                  return self.fetchAnalyserList();
                })
            })
            .catch(function(cantMakeDirErr){
              return doReject(`Error creatomh sidekick analyser directory: ${self.ANALYSER_INSTALL_DIR}`, cantMakeDirErr);
            })
        }
      );

    function canWrite(dir){
      return canAccess(dir, fs.W_OK)
        .then(function(){
          return doResolve();
        })
        .catch(function(err){
          return doReject('Unable to write to sidekick analyser directory', err);
        })
    }
  };

  /**
   * Fetch a list of all the analysers that Sidekick supports
   * @returns {bluebird|exports|module.exports}
   */
  self.fetchAnalyserList = function(){
    const SK_CENTRAL_ANALYSER_LIST_URL = 'https://raw.githubusercontent.com/sidekickcode/analysers/master/analysers.json';

    return request(SK_CENTRAL_ANALYSER_LIST_URL)
      .then(function(response) {
        if(response.statusCode == 200) {
          debug('have analysers list');
          self.ALL_ANALYSERS = JSON.parse(jsonWithComments(response.body));
          return doResolve(self.ALL_ANALYSERS);
        } else {
          debug('analyser list unavailable: ' + JSON.stringify(response, null, 4));
          return doReject('Unable to fetch list of analysers');
        }
      }, function(err){
        debug('error fetching analyser list');
        return doReject('Unable to fetch list of analysers', err);
      })
  };

  /**
   * Fetch the canonical analyser config stored in teh central list of analysers.
   * @param analyserName the name of the analyser to fetch the config for
   * @returns Promise {path: [abs path to analyser], config: [analyser config]}
   */
  self.fetchCanonicalAnalyserConfig = function(analyserName){
    if(!self.ALL_ANALYSERS) {
      return self.fetchAnalyserList()
        .then(function() {
          return returnConfig();
        })
    } else {
      return returnConfig();
    }

    function returnConfig(){
      var analyserConfig = self.ALL_ANALYSERS[analyserName];
      if (analyserConfig) {
        return doResolve(analyserConfig);
      } else {
        return doReject(`Unknown analyser '${analyserName}'`);
      }
    }

  };

  /**
   * Fetch and analyser object to be run (its config and path to its executable).
   * Will install the analyser for a registry if not found on the local install.
   * If no version specified and the analyser does not exist locally, it will install the latest version.
   * @param analyserName the name of the analyser to fetch the config for
   * @param version (optional) the specific version of the analyser to return data for.
   * @returns Promise {path: [abs path to analyser], config: [analyser config]}
   */
  self.fetchAnalyser = function(analyserName, version){
    var pathToAnalyser = path.join(self.ANALYSER_INSTALL_DIR, `${analyserName}@${version}`);

    return exists(pathToAnalyser)
      .then(function(fileStat){
        return readAnalyserConfig(pathToAnalyser)
          .then(function(configObj){
            return doResolve({path: pathToAnalyser, config: configObj});
          });
      }, function(err){
        return doReject(`Unable to fetch config for analyser '${analyserName}'`, err);
      })
  };

  /**
   * Install the analyser from a registry.
   * If the analyser already exists locally (same version) then we just return the config.
   * If no version specified it will install the latest version.
   * @param analyserName the name of the analyser to fetch the config for
   * @param version (optional) the specific version of the analyser to return data for.
   * @returns Promise {path: [abs path to analyser], config: [analyser config]}
   */
  self.installAnalyser = function(analyser){
    var haveVersion;
    if(!analyser.version || analyser.version === 'latest'){
      haveVersion = self.isNewerVersionAvailable(analyser.name);
    } else {
      haveVersion = Promise.resolve({"latest": analyser.version});
    }

    return haveVersion.then(function(version){
      var versionToInstall = version.latest;
      var pathToAnalyser = path.join(self.ANALYSER_INSTALL_DIR, `${analyser.name}@${versionToInstall}`);

      return exists(pathToAnalyser) //checks for @latest as well as specific version
        .then(function(fileStat){
            return readAnalyserConfig(pathToAnalyser)
                .then(function(configObj){
                  return doResolve({path: pathToAnalyser, config: configObj});
                });
            },
            function(err){
              if(err.code === 'ENOENT'){
                //no specific version dir or @latest dir
                return _installAnalyser(analyser, versionToInstall)
                    .then(function(configObj){
                      return doResolve({path: pathToAnalyser, config: configObj});
                    });
              } else {
                return doReject('Cannot read analyser install dir', err);
              }
            }
        )
    });

  };

  /**
   * Get the latest version info for an analyser {newer: [boolean], latest: [string]}
   * @param analyserName
   * @param version
   * @returns {bluebird|exports|module.exports}
   */
  self.isNewerVersionAvailable = function(analyserName, version){
    return getAllAnalyserEntry(analyserName)
      .then(function(analyserConfig){
        var extractor;
        if(analyserConfig.registry === 'npm') {
          extractor = new npmExtractor();
        }
        proxyAll(extractor, self);

        return extractor.getLatestVersion(analyserName)
          .then(function(latestVersion){
            if(semver.valid(version) && semver.valid(latestVersion)){
              return doResolve({"newer" : semver.lt(version, latestVersion), "latest": latestVersion});
            } else {
              if(semver.valid(latestVersion)){
                //we were passed a garbage version - still useful to say what the latest version is
                return doResolve({"latest": latestVersion});
              } else {
                return doReject(`Invalid version '${version}' for analyser '${analyserName}'`);
              }
            }
          })
        })
  };

  /**
   * Validate a list of analysers - removing any unknown analysers
   * @param analysers Array of possible analysers
   * @retuns Array of known analysers
   */
  self.validateAnalyserList = function(analysers){
    var validAnalysers = [];
    debug('analysers: ' + JSON.stringify(analysers));

    return new Promise(function(resolve, reject){
      if(self.ALL_ANALYSERS){
        doResolve();
      } else {
        self.fetchAnalyserList()
          .then(function(ALL_ANALYSER){
            debug('have analyser list: ' + ALL_ANALYSER);
            doResolve();
          });
      }

      function doResolve(){
        _.each(analysers, function(analyser){
          if(self.ALL_ANALYSERS[analyser.name]){
            validAnalysers.push(analyser);
          }
        });
        resolve(validAnalysers);
      }
    });
  };

  /**
   * Read and parse the config for a locally installed analyser
   * @param analyserPath the abs path of the analyser config file
   */
  function readAnalyserConfig(analyserPath) {
    var filePath = path.join(analyserPath, 'config.json');

    return readFile(filePath, {encoding: 'utf8'})
      .then(function(fileContents){
        try {
          return doResolve(JSON.parse(jsonWithComments(fileContents)));
        } catch(err){
          return doReject(`Unable to parse config file for analyser '${analyserPath}'`, err);
        }
      }, function(err){
        return doReject(`Unable to read config file for analyser '${analyserPath}'`, err);
      });
  }

  function _installAnalyser(analyser, version){
    return getAllAnalyserEntry(analyser.name)
      .then(function(analyserConfig){
        var config = analyserConfig.config; //strip the wrapper which includes registry etc..

        if(version !== 'latest' && !semver(version)) {
          return doReject(`Invalid version '${version}' for analyser '${analyser.name}'`);
        }

        var extractor;
        //TODO - support other registries (extractors shoudl have common interface (fetch func and ee)
        if(analyserConfig.registry === 'npm') {
          extractor = new npmExtractor();
        } else {
          return doReject(`Unknown registry '${analyserConfig.registry}'`);
        }
        proxyAll(extractor, self);

        return extractor.fetch(analyser, version, self.ANALYSER_INSTALL_DIR)
          .then(function(){
            return doResolve(config);  //return the newly installed analyser config
          })
      })
  }

  function getAllAnalyserEntry(analyserName){
    return self.fetchAnalyserList()
      .then(function (ALL_ANALYSERS) {
        var analyserConfig = ALL_ANALYSERS[analyserName];
        if (analyserConfig) {
          return doResolve(analyserConfig);
        } else {
          return Promise.reject(new UnknownAnalyserError(analyserName));
        }
      })
  }

  function doResolve(stuff){
    return Promise.resolve(stuff);
  }
  function doReject(errMsg, err){
    if(err && err.message){
      return Promise.reject(Error(`${errMsg}\n${err.message}`, err));
    } else {
      return Promise.reject(Error(errMsg, err));
    }
  }

}

inherits(AnalyserManager, EventEmitter);
<|endoftext|>


<commit_before>/*
 * remote.js: Commands related to working with remote configs
 *
 * (C) 2012, Nodejitsu Inc.
 *
 */

var fs = require('fs'),
    quill = require('../../quill');

var remote = exports;

remote.usage = [
  '`quill remote` commands allow you to work with remote configs',
  '',
  'quill remote create <name>',
  'quill remote list',
  'quill remote delete <name>',
  'quill remote view <name>',
  'quill remote get <name> <key>',
  'quill remote set <name> <key> <value>',
  'quill remote clear <name> <key>',
  'quill remote load <name> <file>'
];

//
// ### function create (name, callback)
// Creates a remote config called `name`.
//
remote.create = function (name, callback) {
  if (name) {
    quill.prompt.override.name = name;
  }

  quill.prompt.get(['name'], function (err, result) {
    if (err) {
      return callback(err);
    }

    quill.log.info('Creating remote config: ' + result.name.magenta);
    quill.remote.create(result.name, {}, callback);
  });
};

//
// Usage for `quill remote create`
//
remote.create.usage = [
  'Creates a remote config called <name>',
  '',
  'quill remote create <name>'
];

//
// ### function list (callback)
// Lists remote configs.
//
remote.list = function (callback) {
  quill.remote.list(function (err, remotes) {
    if (err) {
      return callback(err);
    }
    else if (!remotes || !remotes.length) {
      quill.log.warn('No remotes found');
      return callback();
    }

    var rows = [['name']],
        colors = ['underline'];

    remotes.forEach(function (remote) {
      rows.push([remote.name]);
    });

    quill.inspect.putRows('data', rows, colors);
    callback();
  });
};

//
// Usage for `quill remote list`
//
remote.create.usage = [
  'Lists named remote configurations.',
  '',
  'quill remote list'
];

//
// ### function delete (name, callback)
// Attempts to delete the remote configuration with `name`.
//
remote.delete = function (name, callback) {
  if (name) {
    quill.prompt.override.name = name;
  }

  quill.prompt.get(['name'], function (err, result) {
    if (err) {
      return callback(err);
    }

    quill.log.info('Deleting remote config: ' + result.name.magenta);
    quill.remote.destroy(result.name, callback);
  });
};

//
// Usage for `quill remote delete`
//
remote.delete.usage = [
  'Attempts to delete the remote configuration with <name>.',
  '',
  'quill remote delete <name>'
];

//
// ### function view (name, callback)
// Views the remote configuration with `name`.
//
remote.view = function (name, callback) {
  if (name) {
    quill.prompt.override.name = name;
  }

  quill.prompt.get(['name'], function (err, result) {
    if (err) {
      return callback(err);
    }

    quill.log.info('Viewing remote config: ' + result.name.magenta);
    quill.remote.get(result.name, function (err, remote) {
      if (err) {
        return callback(err);
      }

      quill.inspect.putObject(remote);
      callback();
    });
  });
};

//
// Usage for `quill remote view <name>`
//
remote.view.usage = [
  'Views the remote configuration with <name>.',
  '',
  'quill remote view <name>'
];

//
// ### function get (name, key, callback)
// Displays the value of the `key` in the remote configuration with `name`.
//
remote.get = function (name, key, callback) {
  if (!name || !key) {
    return callback(new Error('Config name and key required.'));
  }

  quill.remote.get(name, function (err, remote) {
    if (err) {
      return callback(err);
    }

    quill.log.data(key.yellow + ' ' + remote.settings[key].magenta);
    callback();
  });
};

//
// Usage for `quill remote get <name> <key>`
//
remote.get.usage = [
  'Displays the value of the <key> in the remote configuration with <name>.',
  '',
  'quill remote get <name> <key>'
];

//
// ### function set (name, key, value, callback)
// Sets the `key` to `value` in the remote configuration with `name`.
//
remote.set = function (name, key, value, callback) {
  if (!name || !key || !value) {
    return callback(new Error('Config name, key and value required.'));
  }

  quill.remote.set(name, key, value, callback);
};

//
// Usage for `quill remote set <name> <key> <value>`
//
remote.set.usage = [
  'Sets the <key> to <value> in the remote configuration with <name>.',
  '',
  'quill remote set <name> <key> <value>'
];

//
// ### function clear (name, key, callback)
// Clears the `key` in the remote configuration with `name`.
//
remote.clear = function (name, key, callback) {
  if (!name || !key) {
    return callback(new Error('Config name and key required.'));
  }

  quill.remote.clear(name, key, callback);
};

//
// Usage for `quill remote clear <name> <key>`
//
remote.clear.usage = [
  'Clears the <key> in the remote configuration with <name>.',
  '',
  'quill remote clear <name> <key>'
];

//
// ### function load (name, file, callback)
// Loads all keys and values in `file` into the remote configuration with `name`.
// Warning: will overwrite any existing values
//
remote.load = function (name, file, callback) {
  if (!name || !file) {
    return callback(new Error('Config name and file required.'));
  }

  quill.log.info('Loading file ' + file.magenta + ' into ' + name.magenta + ' config');

  fs.readFile(file, function (err, data) {
    if (err) {
      return callback(err);
    }

    try { data = JSON.parse(data) }
    catch (ex) { return callback(ex) }

    quill.remote.destroy(name, function () {
      //
      // Ignore errors here.
      //
      quill.remote.create(name, data, callback);
    });
  });
};

//
// Usage for `quill remote load <name> <file>`
//
remote.load.usage = [
  'Loads all keys and values in <file> into the remote configuration with <name>.',
  'Warning: will overwrite any existing values',
  '',
  'quill remote load <name> <file>'
];

//
// ### function merge (name, file, callback)
// Merges all keys and values in `file` into remote configuration with `name`.
//
remote.merge = function (name, file, callback) {
  if (!name || !file) {
    return callback(new Error('Config name and file required.'));
  }

  quill.log.info('Merging file ' + file.magenta + ' into ' + name.magenta + ' config');

  fs.readFile(file, function (err, data) {
    if (err) {
      return callback(err);
    }

    try { data = JSON.parse(data) }
    catch (ex) { return callback(ex) }

    //
    // Instead of merging config on the server side, merge it locally:
    // fetch it, merge and recreate.
    //
    quill.remote.get(name, function (err, remote) {
      if (err) {
        return callback(err);
      }

      quill.remote.destroy(name, function () {
        if (err) {
          return callback(err);
        }

        Object.keys(data).forEach(function (key) {
          remote[key] = data[key];
        });

        quill.remote.create(name, remote, callback);
      });
    });
  });
};

//
// Usage for `quill remote merge <name> <file>`
//
remote.merge.usage = [
  'Merges all keys and values in <file> into remote configuration with <name>.',
  '',
  'quill remote merge <name> <file>'
];<commit_msg>[fix] Only view `remote.settings` in `quill remote view <name>`<commit_after>/*
 * remote.js: Commands related to working with remote configs
 *
 * (C) 2012, Nodejitsu Inc.
 *
 */

var fs = require('fs'),
    quill = require('../../quill');

var remote = exports;

remote.usage = [
  '`quill remote` commands allow you to work with remote configs',
  '',
  'quill remote create <name>',
  'quill remote list',
  'quill remote delete <name>',
  'quill remote view <name>',
  'quill remote get <name> <key>',
  'quill remote set <name> <key> <value>',
  'quill remote clear <name> <key>',
  'quill remote load <name> <file>'
];

//
// ### function create (name, callback)
// Creates a remote config called `name`.
//
remote.create = function (name, callback) {
  if (name) {
    quill.prompt.override.name = name;
  }

  quill.prompt.get(['name'], function (err, result) {
    if (err) {
      return callback(err);
    }

    quill.log.info('Creating remote config: ' + result.name.magenta);
    quill.remote.create(result.name, {}, callback);
  });
};

//
// Usage for `quill remote create`
//
remote.create.usage = [
  'Creates a remote config called <name>',
  '',
  'quill remote create <name>'
];

//
// ### function list (callback)
// Lists remote configs.
//
remote.list = function (callback) {
  quill.remote.list(function (err, remotes) {
    if (err) {
      return callback(err);
    }
    else if (!remotes || !remotes.length) {
      quill.log.warn('No remotes found');
      return callback();
    }

    var rows = [['name']],
        colors = ['underline'];

    remotes.forEach(function (remote) {
      rows.push([remote.name]);
    });

    quill.inspect.putRows('data', rows, colors);
    callback();
  });
};

//
// Usage for `quill remote list`
//
remote.create.usage = [
  'Lists named remote configurations.',
  '',
  'quill remote list'
];

//
// ### function delete (name, callback)
// Attempts to delete the remote configuration with `name`.
//
remote.delete = function (name, callback) {
  if (name) {
    quill.prompt.override.name = name;
  }

  quill.prompt.get(['name'], function (err, result) {
    if (err) {
      return callback(err);
    }

    quill.log.info('Deleting remote config: ' + result.name.magenta);
    quill.remote.destroy(result.name, callback);
  });
};

//
// Usage for `quill remote delete`
//
remote.delete.usage = [
  'Attempts to delete the remote configuration with <name>.',
  '',
  'quill remote delete <name>'
];

//
// ### function view (name, callback)
// Views the remote configuration with `name`.
//
remote.view = function (name, callback) {
  if (name) {
    quill.prompt.override.name = name;
  }

  quill.prompt.get(['name'], function (err, result) {
    if (err) {
      return callback(err);
    }

    quill.log.info('Viewing remote config: ' + result.name.magenta);
    quill.remote.get(result.name, function (err, remote) {
      if (err) {
        return callback(err);
      }

      quill.inspect.putObject(remote.settings);
      callback();
    });
  });
};

//
// Usage for `quill remote view <name>`
//
remote.view.usage = [
  'Views the remote configuration with <name>.',
  '',
  'quill remote view <name>'
];

//
// ### function get (name, key, callback)
// Displays the value of the `key` in the remote configuration with `name`.
//
remote.get = function (name, key, callback) {
  if (!name || !key) {
    return callback(new Error('Config name and key required.'));
  }

  quill.remote.get(name, function (err, remote) {
    if (err) {
      return callback(err);
    }

    quill.log.data(key.yellow + ' ' + remote.settings[key].magenta);
    callback();
  });
};

//
// Usage for `quill remote get <name> <key>`
//
remote.get.usage = [
  'Displays the value of the <key> in the remote configuration with <name>.',
  '',
  'quill remote get <name> <key>'
];

//
// ### function set (name, key, value, callback)
// Sets the `key` to `value` in the remote configuration with `name`.
//
remote.set = function (name, key, value, callback) {
  if (!name || !key || !value) {
    return callback(new Error('Config name, key and value required.'));
  }

  quill.remote.set(name, key, value, callback);
};

//
// Usage for `quill remote set <name> <key> <value>`
//
remote.set.usage = [
  'Sets the <key> to <value> in the remote configuration with <name>.',
  '',
  'quill remote set <name> <key> <value>'
];

//
// ### function clear (name, key, callback)
// Clears the `key` in the remote configuration with `name`.
//
remote.clear = function (name, key, callback) {
  if (!name || !key) {
    return callback(new Error('Config name and key required.'));
  }

  quill.remote.clear(name, key, callback);
};

//
// Usage for `quill remote clear <name> <key>`
//
remote.clear.usage = [
  'Clears the <key> in the remote configuration with <name>.',
  '',
  'quill remote clear <name> <key>'
];

//
// ### function load (name, file, callback)
// Loads all keys and values in `file` into the remote configuration with `name`.
// Warning: will overwrite any existing values
//
remote.load = function (name, file, callback) {
  if (!name || !file) {
    return callback(new Error('Config name and file required.'));
  }

  quill.log.info('Loading file ' + file.magenta + ' into ' + name.magenta + ' config');

  fs.readFile(file, function (err, data) {
    if (err) {
      return callback(err);
    }

    try { data = JSON.parse(data) }
    catch (ex) { return callback(ex) }

    quill.remote.destroy(name, function () {
      //
      // Ignore errors here.
      //
      quill.remote.create(name, data, callback);
    });
  });
};

//
// Usage for `quill remote load <name> <file>`
//
remote.load.usage = [
  'Loads all keys and values in <file> into the remote configuration with <name>.',
  'Warning: will overwrite any existing values',
  '',
  'quill remote load <name> <file>'
];

//
// ### function merge (name, file, callback)
// Merges all keys and values in `file` into remote configuration with `name`.
//
remote.merge = function (name, file, callback) {
  if (!name || !file) {
    return callback(new Error('Config name and file required.'));
  }

  quill.log.info('Merging file ' + file.magenta + ' into ' + name.magenta + ' config');

  fs.readFile(file, function (err, data) {
    if (err) {
      return callback(err);
    }

    try { data = JSON.parse(data) }
    catch (ex) { return callback(ex) }

    //
    // Instead of merging config on the server side, merge it locally:
    // fetch it, merge and recreate.
    //
    quill.remote.get(name, function (err, remote) {
      if (err) {
        return callback(err);
      }

      quill.remote.destroy(name, function () {
        if (err) {
          return callback(err);
        }

        Object.keys(data).forEach(function (key) {
          remote[key] = data[key];
        });

        quill.remote.create(name, remote, callback);
      });
    });
  });
};

//
// Usage for `quill remote merge <name> <file>`
//
remote.merge.usage = [
  'Merges all keys and values in <file> into remote configuration with <name>.',
  '',
  'quill remote merge <name> <file>'
];<|endoftext|>


<commit_before>({
    appDir: "static",
    baseUrl: ".",
    dir: "out/dist",
    generateSourceMaps: true,
    preserveLicenseComments: false,
    optimize: "uglify2",
    removeCombined: true,
    useStrict: true,
    mainConfigFile: "static/main.js",
    skipDirOptimize: true,
    optimizeCss: "standard",
    paths: { "vs": "empty:" },
    modules: [
        {
            name: "main"
        }
    ]
})
<commit_msg>Remove ancient app.build.js<commit_after><|endoftext|>


<commit_before>'use strict'
import React from 'react'
import PropTypes from 'prop-types'
import './nav.css'

const Navbar = (props) => {
  const {rightSide, leftSide, header} = props

  let url = './'
  let title
  if (header != null) {
    if (header.title != undefined) {
      if (header.url != null) {
        url = header.url
      }
      title = header.title
    } else {
      title = header
    }
  }

  return (

            <button
              type="button"
              className="navbar-toggle collapsed"
              data-toggle="collapse"
              data-target="#stories-navbar-toggle"
              aria-expanded="false">
              Toggle navigation

            </button>
            {title}

                Manage

                        Create a new story

                       Stories

                       Features

                       Authors

                       Settings

                    Control panel

              {leftSide}

              {rightSide}

  )
}
Navbar.propTypes = {
  leftSide: PropTypes.oneOfType([PropTypes.array,PropTypes.object,]),
  rightSide: PropTypes.oneOfType([PropTypes.array,PropTypes.object,]),
  header: PropTypes.oneOfType([PropTypes.object, PropTypes.string,])
}

export default Navbar
<commit_msg>Corrections to navbar to work with bootstrap 4<commit_after>'use strict'
import React from 'react'
import PropTypes from 'prop-types'
import './nav.css'

const Navbar = (props) => {
  const {rightSide, leftSide, header,} = props

  let url = './'
  let title
  if (header != null) {
    if (header.title != undefined) {
      if (header.url != null) {
        url = header.url
      }
      title = header.title
    } else {
      title = header
    }
  }

  return (

        {title}
        <button
          type="button"
          className="navbar-toggler"
          data-toggle="collapse"
          data-target="#stories-navbar-toggle"
          aria-expanded="false"
          aria-label="Toggle navigation">

        </button>

              Manage

                    Create a new story

                   Stories

                   Features

                   Authors

                   Settings

                Control panel

            {leftSide}

            {rightSide}

  )
}
Navbar.propTypes = {
  leftSide: PropTypes.oneOfType([PropTypes.array, PropTypes.object,]),
  rightSide: PropTypes.oneOfType([PropTypes.array, PropTypes.object,]),
  header: PropTypes.oneOfType([PropTypes.object, PropTypes.string,]),
}

export default Navbar
<|endoftext|>


<commit_before>
var lineReader = require('line-reader');
var sys = require('sys');
var exec = require('child_process').exec;
var Promise = require('bluebird');

var moduleArr = [];
var fileName = process.argv[2];

function storingModuleNames(){

var eachLine = Promise.promisify(lineReader.eachLine);

    eachLine(fileName, function(line) {
      if (line.indexOf('require') != -1){
      var regex = /require\(([^)]+)\)/g;
      var mat = regex.exec(line);

      mat[1] = mat[1].replace(/'/g, '');
      moduleArr.push(mat[1]);
    }
    }).then(function() {
      runningCommand(moduleArr);
    }).catch(function(err) {
      console.error(err);
    });
};

function runningCommand(modules){
    for (var module in modules){

      var globalCommand = 'npm install -g '+modules[module];
      var localCommand = 'npm install '+modules[module]+' --save';

      function puts(error, stdout, stderr) { sys.puts(stdout) }
      exec(globalCommand, puts);
      exec(localCommand, puts);
    }
  };

var compute = function() {

  return new Promise(function(resolve) {
          if(process.argv[2]!=null)
            storingModuleNames();
          else
            console.error('A filename should be passed as argument');
        })
        .catch(function (e) {
            throw e;
        });
};

compute();<commit_msg>Setting npm-install-all to env mode<commit_after>#!/usr/bin/env node

var lineReader = require('line-reader');
var sys = require('sys');
var exec = require('child_process').exec;
var Promise = require('bluebird');

var moduleArr = [];
var fileName = process.argv[2];

function storingModuleNames(){

var eachLine = Promise.promisify(lineReader.eachLine);

    eachLine(fileName, function(line) {
      if (line.indexOf('require') != -1){
      var regex = /require\(([^)]+)\)/g;
      var mat = regex.exec(line);

      mat[1] = mat[1].replace(/'/g, '');
      moduleArr.push(mat[1]);
    }
    }).then(function() {
      runningCommand(moduleArr);
    }).catch(function(err) {
      console.error(err);
    });
};

function runningCommand(modules){
    for (var module in modules){

      var globalCommand = 'npm install -g '+modules[module];
      var localCommand = 'npm install '+modules[module]+' --save';

      function puts(error, stdout, stderr) { sys.puts(stdout) }
      exec(globalCommand, puts);
      exec(localCommand, puts);
    }
  };

var compute = function() {

  return new Promise(function(resolve) {
          if(process.argv[2]!=null)
            storingModuleNames();
          else
            console.error('A filename should be passed as argument');
        })
        .catch(function (e) {
            throw e;
        });
};

compute();<|endoftext|>