<commit_before>class Model {
  constructor(data = {}) {
    Object.values(this.constructor.virtuals).forEach(virtual => {
      const name = virtual.name;
      let { get, set } = virtual;

      if (get) {
        get = get.bind(this);
      }
      if (set) {
        set = set.bind(this);
      }

      Object.defineProperty(this, name, {
        get,
        set,
        enumerable: true
      });
    });

    this.setData(data);
  }

  getField(name) {
    // TODO: move this to the Model.fields getter?
    const field = this.constructor.fields[name];
    if (!field) {
      // TODO: throw ModelError
      throw new Error(`Unknown field '${this.constructor.name}.${name}'`);
    }
    return field;
  }

  getFields(fields) {
    if (!fields || !fields.length) {
      return Object.values(this.constructor.fields);
    }
    return fields.map(field => {
      if (typeof field === 'string') {
        field = this.getField(field);
      }
      return field;
    });
  }

  setDefaults({ fields } = {}) {
    this.getFields(fields).forEach(field => {
      const name = field.name;

      if (this[name] === undefined) {
        if (field.hasDefault()) {
          this[name] = field.getDefault(this);
        }
      }
    });

    return this;
  }

  setData(data) {
    Object.keys(data).forEach(name => {
      const value = data[name];
      const field = this.constructor.fields[name];

      if (field) {
        // TODO: add support for casting referenced models to id
        // ie this.someId = value.id;
        this[name] = value;
      } else {
        const virtual = this.constructor.virtuals[name];
        if (!virtual) {
          // TODO: remove this check, unnecessary restriction..
          throw new Error(
            `Unknown field or virtual '${this.constructor.name}.${name}'`
          );
        }
        if (!virtual.hasSetter()) {
          throw new Error(
            `Virtual '${this.constructor.name}.${name}' has no setter`
          );
        }
        this[name] = value;
      }
    });

    return this;
  }

  _getFieldData(fields) {
    return this.getFields(fields).reduce((data, field) => {
      const name = field.name;
      const value = this[name];

      if (value !== undefined) {
        data[name] = value;
      }

      return data;
    }, {});
  }

  async getData({ fields, virtuals } = {}) {
    const data = this._getFieldData(fields);

    if (virtuals) {
      if (!Array.isArray(virtuals) || !virtuals.length) {
        virtuals = Object.values(this.constructor.virtuals)
          .filter(virtual => virtual.hasGetter())
          .map(virtual => virtual.name);
      }
      const virtualsData = await Promise.all(
        virtuals.map(async name => {
          const virtual = this.constructor.virtuals[name];
          if (!virtual.get) {
            throw new Error(
              `Virtual '${this.constructor.name}.${name}' has no getter`
            );
          }
          return virtual.get.call(this);
        })
      );
      virtuals.forEach((name, index) => {
        data[name] = virtualsData[index];
      });
    }

    return data;
  }

  async validate({ fields } = {}) {
    await Promise.all(
      this.getFields(fields).map(async field => {
        const name = field.name;
        const value = this[name];
        await field.validate(value, this);
      })
    );

    return this;
  }

  cast({ fields, forSave, forFetch } = {}) {
    this.getFields(fields).forEach(field => {
      const name = field.name;
      const value = this[name];

      if (value !== undefined) {
        const newValue = field.cast(value, this, { forSave, forFetch });
        if (newValue !== undefined) {
          this[name] = newValue;
        }
      }
    });

    return this;
  }

  getQuery({ forInsert }, options = {}) {
    const query = this.constructor.query.setOptions(options).first(true);

    if (options.require === undefined) {
      query.require(true);
    }
    if (forInsert) {
      return query;
    }

    const primaryField = this.constructor.primary.name;
    const primary = this[primaryField];

    if (primary === undefined) {
      const model = this.constructor.name;
      throw new Error(
        `${model}: primary field (\`${primaryField}\`) is not set`
      );
    }

    return query.where({ [primaryField]: primary }).forge(false);
  }

  async fetch(options) {
    const row = await this.getQuery({ forFetch: true }, options).fetch();
    return row ? this.setData(row) : row;
  }

  async delete(options) {
    const row = await this.getQuery({ forDelete: true }, options).delete();
    return row ? this.setData(row) : row;
  }

  async update(options) {
    const row = await this.getQuery({ forUpdate: true }, options).update(this);
    return row ? this.setData(row) : row;
  }

  async save(options) {
    return this[this.constructor.primary.name] === undefined
      ? this.insert(options)
      : this.update(options);
  }

  async insert(options) {
    return this.getQuery({ forInsert: true }, options).insert(this);
  }

  static async count(options) {
    return this.query.count(options);
  }

  static async save(data, options) {
    return this.query.save(data, options);
  }

  static async insert(data, options) {
    return this.query.insert(data, options);
  }

  static async update(data, options) {
    return this.query.update(data, options);
  }

  static async fetch(options) {
    return this.query.fetch(options);
  }

  static async delete(options) {
    return this.query.delete(options);
  }

  static async fetchByPrimaryField(primary, options) {
    return new this({ [this.primary.name]: primary }).fetch(options);
  }

  static async deleteByPrimaryField(primary, options) {
    return new this({ [this.primary.name]: primary }).delete(options);
  }

  static async updateByPrimaryField(primary, data, options) {
    return new this(
      Object.assign({}, data, { [this.primary.name]: primary })
    ).update(options);
  }

  static _inheritConfig() {
    if (!this._config) {
      Object.defineProperty(this, '_config', {
        value: {
          name: this.name,
          references: {},
          fields: {},
          virtuals: {}
        },
        writable: true
      });
    }
    const parent = this._config;
    if (parent.name !== this.name) {
      const clone = (items, item) => {
        items[item.name] = item.clone({ model: this });
        return items;
      };
      const inherited = Object.assign(
        {},
        {
          name: this.name,
          references: Object.assign({}, parent.references),
          fields: Object.values(parent.fields).reduce(clone, {}),
          virtuals: Object.values(parent.virtuals).reduce(clone, {})
        }
      );
      if (parent.primary) {
        inherited.primary = inherited.fields[parent.primary.name];
      }
      this._config = inherited;
    }
  }

  static getReferences() {
    this._inheritConfig();
    return this._config.references;
  }

  static getFields() {
    this._inheritConfig();
    return this._config.fields;
  }

  static setFields(fields) {
    this._inheritConfig();
    Object.keys(fields).forEach(name => {
      if (this.prototype[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add field \`${name}\` ` +
            `(\`${this.name}.prototype.${name}\` is already assigned)`
        );
      }
      if (this._config.virtuals[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add field \`${name}\` ` +
            `(\`${name}\` is a virtual)`
        );
      }
      const field = new this.Field(
        Object.assign({}, fields[name], {
          name,
          model: this
        })
      );
      if (field.references) {
        this._config.references[field.name] = field.references;
      }
      if (field.primary) {
        this._config.primary = field;
      }
      this._config.fields[name] = field;
    });
  }

  static getVirtuals() {
    this._inheritConfig();
    return this._config.virtuals;
  }

  static setVirtuals(virtuals) {
    this._inheritConfig();
    Object.keys(virtuals).forEach(name => {
      if (this.prototype[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add virtual \`${name}\` ` +
            `(\`${this.name}.prototype.${name}\` is already assigned)`
        );
      }
      if (this._config.fields[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add virtual \`${name}\` ` +
            `(\`${name}\` is a field)`
        );
      }
      this._config.virtuals[name] = new this.Virtual({
        name,
        model: this,
        descriptor: virtuals[name]
      });
    });
  }

  static getPrimary() {
    this._inheritConfig();
    const primary = this._config.primary;
    if (!primary) {
      throw new Error(`\`${this.name}\` has no primary field`);
    }
    return primary;
  }

  static get references() {
    return this.getReferences();
  }

  static get fields() {
    return this.getFields();
  }

  static set fields(fields) {
    this.setFields(fields);
  }

  static get virtuals() {
    return this.getVirtuals();
  }

  static set virtuals(virtuals) {
    this.setVirtuals(virtuals);
  }

  static get primary() {
    return this.getPrimary();
  }

  static get query() {
    return new this.Query(this);
  }

  static set query(val) {
    throw new Error(`${this.name}.query cannot be overwriten`);
  }
}

module.exports = Model;

// circular deps
Model.Field = require('./Field');
Model.Virtual = require('./Virtual');
Model.Query = require('./Query');
<commit_msg>fix(Model): fix inheritance<commit_after>class Model {
  constructor(data = {}) {
    Object.values(this.constructor.virtuals).forEach(virtual => {
      const name = virtual.name;
      let { get, set } = virtual;

      if (get) {
        get = get.bind(this);
      }
      if (set) {
        set = set.bind(this);
      }

      Object.defineProperty(this, name, {
        get,
        set,
        enumerable: true
      });
    });

    this.setData(data);
  }

  getField(name) {
    // TODO: move this to the Model.fields getter?
    const field = this.constructor.fields[name];
    if (!field) {
      // TODO: throw ModelError
      throw new Error(`Unknown field '${this.constructor.name}.${name}'`);
    }
    return field;
  }

  getFields(fields) {
    if (!fields || !fields.length) {
      return Object.values(this.constructor.fields);
    }
    return fields.map(field => {
      if (typeof field === 'string') {
        field = this.getField(field);
      }
      return field;
    });
  }

  setDefaults({ fields } = {}) {
    this.getFields(fields).forEach(field => {
      const name = field.name;

      if (this[name] === undefined) {
        if (field.hasDefault()) {
          this[name] = field.getDefault(this);
        }
      }
    });

    return this;
  }

  setData(data) {
    Object.keys(data).forEach(name => {
      const value = data[name];
      const field = this.constructor.fields[name];

      if (field) {
        // TODO: add support for casting referenced models to id
        // ie this.someId = value.id;
        this[name] = value;
      } else {
        const virtual = this.constructor.virtuals[name];
        if (!virtual) {
          // TODO: remove this check, unnecessary restriction..
          throw new Error(
            `Unknown field or virtual '${this.constructor.name}.${name}'`
          );
        }
        if (!virtual.hasSetter()) {
          throw new Error(
            `Virtual '${this.constructor.name}.${name}' has no setter`
          );
        }
        this[name] = value;
      }
    });

    return this;
  }

  _getFieldData(fields) {
    return this.getFields(fields).reduce((data, field) => {
      const name = field.name;
      const value = this[name];

      if (value !== undefined) {
        data[name] = value;
      }

      return data;
    }, {});
  }

  async getData({ fields, virtuals } = {}) {
    const data = this._getFieldData(fields);

    if (virtuals) {
      if (!Array.isArray(virtuals) || !virtuals.length) {
        virtuals = Object.values(this.constructor.virtuals)
          .filter(virtual => virtual.hasGetter())
          .map(virtual => virtual.name);
      }
      const virtualsData = await Promise.all(
        virtuals.map(async name => {
          const virtual = this.constructor.virtuals[name];
          if (!virtual.get) {
            throw new Error(
              `Virtual '${this.constructor.name}.${name}' has no getter`
            );
          }
          return virtual.get.call(this);
        })
      );
      virtuals.forEach((name, index) => {
        data[name] = virtualsData[index];
      });
    }

    return data;
  }

  async validate({ fields } = {}) {
    await Promise.all(
      this.getFields(fields).map(async field => {
        const name = field.name;
        const value = this[name];
        await field.validate(value, this);
      })
    );

    return this;
  }

  cast({ fields, forSave, forFetch } = {}) {
    this.getFields(fields).forEach(field => {
      const name = field.name;
      const value = this[name];

      if (value !== undefined) {
        const newValue = field.cast(value, this, { forSave, forFetch });
        if (newValue !== undefined) {
          this[name] = newValue;
        }
      }
    });

    return this;
  }

  getQuery({ forInsert }, options = {}) {
    const query = this.constructor.query.setOptions(options).first(true);

    if (options.require === undefined) {
      query.require(true);
    }
    if (forInsert) {
      return query;
    }

    const primaryField = this.constructor.primary.name;
    const primary = this[primaryField];

    if (primary === undefined) {
      const model = this.constructor.name;
      throw new Error(
        `${model}: primary field (\`${primaryField}\`) is not set`
      );
    }

    return query.where({ [primaryField]: primary }).forge(false);
  }

  async fetch(options) {
    const row = await this.getQuery({ forFetch: true }, options).fetch();
    return row ? this.setData(row) : row;
  }

  async delete(options) {
    const row = await this.getQuery({ forDelete: true }, options).delete();
    return row ? this.setData(row) : row;
  }

  async update(options) {
    const row = await this.getQuery({ forUpdate: true }, options).update(this);
    return row ? this.setData(row) : row;
  }

  async save(options) {
    return this[this.constructor.primary.name] === undefined
      ? this.insert(options)
      : this.update(options);
  }

  async insert(options) {
    return this.getQuery({ forInsert: true }, options).insert(this);
  }

  static async count(options) {
    return this.query.count(options);
  }

  static async save(data, options) {
    return this.query.save(data, options);
  }

  static async insert(data, options) {
    return this.query.insert(data, options);
  }

  static async update(data, options) {
    return this.query.update(data, options);
  }

  static async fetch(options) {
    return this.query.fetch(options);
  }

  static async delete(options) {
    return this.query.delete(options);
  }

  static async fetchByPrimaryField(primary, options) {
    return new this({ [this.primary.name]: primary }).fetch(options);
  }

  static async deleteByPrimaryField(primary, options) {
    return new this({ [this.primary.name]: primary }).delete(options);
  }

  static async updateByPrimaryField(primary, data, options) {
    return new this(
      Object.assign({}, data, { [this.primary.name]: primary })
    ).update(options);
  }

  static _inheritConfig() {
    if (!this._config) {
      Object.defineProperty(this, '_config', {
        value: {
          model: this,
          references: {},
          fields: {},
          virtuals: {}
        },
        writable: true
      });
    }
    if (this._config.model !== this) {
      const clone = (items, item) => {
        items[item.name] = item.clone({ model: this });
        return items;
      };
      const parent = this._config;
      const inherited = {
        model: this,
        references: Object.assign({}, parent.references),
        fields: Object.values(parent.fields).reduce(clone, {}),
        virtuals: Object.values(parent.virtuals).reduce(clone, {})
      };
      if (parent.primary) {
        inherited.primary = inherited.fields[parent.primary.name];
      }
      this._config = inherited;
    }
  }

  static getReferences() {
    this._inheritConfig();
    return this._config.references;
  }

  static getFields() {
    this._inheritConfig();
    return this._config.fields;
  }

  static setFields(fields) {
    this._inheritConfig();
    Object.keys(fields).forEach(name => {
      if (this.prototype[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add field \`${name}\` ` +
            `(\`${this.name}.prototype.${name}\` is already assigned)`
        );
      }
      if (this._config.virtuals[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add field \`${name}\` ` +
            `(\`${name}\` is a virtual)`
        );
      }
      const field = new this.Field(
        Object.assign({}, fields[name], {
          name,
          model: this
        })
      );
      if (field.references) {
        this._config.references[field.name] = field.references;
      }
      if (field.primary) {
        this._config.primary = field;
      }
      this._config.fields[name] = field;
    });
  }

  static getVirtuals() {
    this._inheritConfig();
    return this._config.virtuals;
  }

  static setVirtuals(virtuals) {
    this._inheritConfig();
    Object.keys(virtuals).forEach(name => {
      if (this.prototype[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add virtual \`${name}\` ` +
            `(\`${this.name}.prototype.${name}\` is already assigned)`
        );
      }
      if (this._config.fields[name] !== undefined) {
        throw new Error(
          `${this.name}: cannot add virtual \`${name}\` ` +
            `(\`${name}\` is a field)`
        );
      }
      this._config.virtuals[name] = new this.Virtual({
        name,
        model: this,
        descriptor: virtuals[name]
      });
    });
  }

  static getPrimary() {
    this._inheritConfig();
    const primary = this._config.primary;
    if (!primary) {
      throw new Error(`\`${this.name}\` has no primary field`);
    }
    return primary;
  }

  static get references() {
    return this.getReferences();
  }

  static get fields() {
    return this.getFields();
  }

  static set fields(fields) {
    this.setFields(fields);
  }

  static get virtuals() {
    return this.getVirtuals();
  }

  static set virtuals(virtuals) {
    this.setVirtuals(virtuals);
  }

  static get primary() {
    return this.getPrimary();
  }

  static get query() {
    return new this.Query(this);
  }

  static set query(val) {
    throw new Error(`${this.name}.query cannot be overwriten`);
  }
}

module.exports = Model;

// circular deps
Model.Field = require('./Field');
Model.Virtual = require('./Virtual');
Model.Query = require('./Query');
<|endoftext|>


<commit_before>/*************************************************
 * Copyright (c) 2016 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

/**
 * @ngdoc function
 * @name controllers.function:Inventories
 * @description This controller's for the Inventory page
 */

function InventoriesList($scope, $rootScope, $location, $log,
    $stateParams, $compile, $filter, sanitizeFilter, Rest, Alert, InventoryList,
    generateList, Prompt, SearchInit, PaginateInit, ReturnToCaller,
    ClearScope, ProcessErrors, GetBasePath, Wait,
    Find, Empty, $state) {

    var list = InventoryList,
        defaultUrl = GetBasePath('inventory') + ($stateParams.status === 'sync-failed' ? '?not__inventory_sources_with_failures=0' : ''),
        view = generateList,
        paths = $location.path().replace(/^\//, '').split('/'),
        mode = (paths[0] === 'inventories') ? 'edit' : 'select';

    function ellipsis(a) {
        if (a.length > 20) {
            return a.substr(0,20) + '...';
        }
        return a;
    }

    function attachElem(event, html, title) {
        var elem = $(event.target).parent();
        try {
            elem.tooltip('hide');
            elem.popover('destroy');
        }
        catch(err) {
            //ignore
        }
        $('.popover').each(function() {
            // remove lingering popover
. Seems to be a bug in TB3 RC1
            $(this).remove();
        });
        $('.tooltip').each( function() {
            // close any lingering tool tipss
            $(this).hide();
        });
        elem.attr({
            "aw-pop-over": html,
            "data-popover-title": title,
            "data-placement": "right" });
        $compile(elem)($scope);
        elem.on('shown.bs.popover', function() {
            $('.popover').each(function() {
                $compile($(this))($scope);  //make nested directives work!
            });
            $('.popover-content, .popover-title').click(function() {
                elem.popover('hide');
            });
        });
        elem.popover('show');
    }

    view.inject(InventoryList, { mode: mode, scope: $scope });
    $rootScope.flashMessage = null;

    SearchInit({
        scope: $scope,
        set: 'inventories',
        list: list,
        url: defaultUrl
    });

    PaginateInit({
        scope: $scope,
        list: list,
        url: defaultUrl
    });

    if ($stateParams.name) {
        $scope[InventoryList.iterator + 'InputDisable'] = false;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.name;
        $scope[InventoryList.iterator + 'SearchField'] = 'name';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.name.label;
        $scope[InventoryList.iterator + 'SearchSelectValue'] = null;
    }

    if ($stateParams.has_active_failures) {
        $scope[InventoryList.iterator + 'InputDisable'] = true;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.has_active_failures;
        $scope[InventoryList.iterator + 'SearchField'] = 'has_active_failures';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_active_failures.label;
        $scope[InventoryList.iterator + 'SearchSelectValue'] = ($stateParams.has_active_failures === 'true') ? {
            value: 1
        } : {
            value: 0
        };
    }

    if ($stateParams.has_inventory_sources) {
        $scope[InventoryList.iterator + 'InputDisable'] = true;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.has_inventory_sources;
        $scope[InventoryList.iterator + 'SearchField'] = 'has_inventory_sources';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_inventory_sources.label;
        $scope[InventoryList.iterator + 'SearchSelectValue'] = ($stateParams.has_inventory_sources === 'true') ? {
            value: 1
        } : {
            value: 0
        };
    }

    if ($stateParams.inventory_sources_with_failures) {
        // pass a value of true, however this field actually contains an integer value
        $scope[InventoryList.iterator + 'InputDisable'] = true;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.inventory_sources_with_failures;
        $scope[InventoryList.iterator + 'SearchField'] = 'inventory_sources_with_failures';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.inventory_sources_with_failures.label;
        $scope[InventoryList.iterator + 'SearchType'] = 'gtzero';
    }

    $scope.search(list.iterator);

    if ($scope.removePostRefresh) {
        $scope.removePostRefresh();
    }
    $scope.removePostRefresh = $scope.$on('PostRefresh', function () {
        //If we got here by deleting an inventory, stop the spinner and cleanup events
        Wait('stop');
        try {
            $('#prompt-modal').modal('hide');
        }
        catch(e) {
            // ignore
        }
        $scope.inventories.forEach(function(inventory, idx) {
            $scope.inventories[idx].launch_class = "";
            if (inventory.has_inventory_sources) {
                if (inventory.inventory_sources_with_failures > 0) {
                    $scope.inventories[idx].syncStatus = 'error';
                    $scope.inventories[idx].syncTip = inventory.inventory_sources_with_failures + ' groups with sync failures. Click for details';
                }
                else {
                    $scope.inventories[idx].syncStatus = 'successful';
                    $scope.inventories[idx].syncTip = 'No inventory sync failures. Click for details.';
                }
            }
            else {
                $scope.inventories[idx].syncStatus = 'na';
                $scope.inventories[idx].syncTip = 'Not configured for inventory sync.';
                $scope.inventories[idx].launch_class = "btn-disabled";
            }
            if (inventory.has_active_failures) {
                $scope.inventories[idx].hostsStatus = 'error';
                $scope.inventories[idx].hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.';
            }
            else if (inventory.total_hosts) {
                $scope.inventories[idx].hostsStatus = 'successful';
                $scope.inventories[idx].hostsTip = 'No hosts with failures. Click for details.';
            }
            else {
                $scope.inventories[idx].hostsStatus = 'none';
                $scope.inventories[idx].hostsTip = 'Inventory contains 0 hosts.';
            }
        });
    });

    if ($scope.removeRefreshInventories) {
        $scope.removeRefreshInventories();
    }
    $scope.removeRefreshInventories = $scope.$on('RefreshInventories', function () {
        // Reflect changes after inventory properties edit completes
        $scope.search(list.iterator);
    });

    if ($scope.removeHostSummaryReady) {
        $scope.removeHostSummaryReady();
    }
    $scope.removeHostSummaryReady = $scope.$on('HostSummaryReady', function(e, event, data) {

        var html, title = "Recent Jobs";
        Wait('stop');
        if (data.count > 0) {
            html = "
\n";
            html += "
\n";
            html += "
";
            html += "Status	";
            html += "Finished	";
            html += "Name	";
            html += "
\n";
            html += "
\n";
            html += "
\n";

            data.results.forEach(function(row) {
                html += "
\n";
                html += "	\n";
                html += "" + ($filter('longDate')(row.finished)).replace(/ /,'
') + "	";
                html += "" + $filter('sanitize')(ellipsis(row.name)) + "	";
                html += "
\n";
            });
            html += "
\n";
            html += "
\n";
        }
        else {
            html = "
No recent job data available for this inventory.
\n";
        }
        attachElem(event, html, title);
    });

    if ($scope.removeGroupSummaryReady) {
        $scope.removeGroupSummaryReady();
    }
    $scope.removeGroupSummaryReady = $scope.$on('GroupSummaryReady', function(e, event, inventory, data) {
        var html, title;

        Wait('stop');

        // Build the html for our popover
        html = "
\n";
        html += "
\n";
        html += "
";
        html += "Status	";
        html += "Last Sync	";
        html += "Group	";
        html += "
";
        html += "
\n";
        html += "
\n";
        data.results.forEach( function(row) {
            if (row.related.last_update) {
                html += "
";
                html += `	`;
                html += "" + ($filter('longDate')(row.last_updated)).replace(/ /,'
') + "	";
                html += "" + ellipsis(row.summary_fields.group.name) + "	";
                html += "
\n";
            }
            else {
                html += "
";
                html += "	";
                html += "NA	";
                html += "" + ellipsis(row.summary_fields.group.name) + "	";
                html += "
\n";
            }
        });
        html += "
\n";
        html += "
\n";
        title = "Sync Status";
        attachElem(event, html, title);
    });

    $scope.showGroupSummary = function(event, id) {
        var inventory;
        if (!Empty(id)) {
            inventory = Find({ list: $scope.inventories, key: 'id', val: id });
            if (inventory.syncStatus !== 'na') {
                Wait('start');
                Rest.setUrl(inventory.related.inventory_sources + '?or__source=ec2&or__source=rax&order_by=-last_job_run&page_size=5');
                Rest.get()
                    .success(function(data) {
                        $scope.$emit('GroupSummaryReady', event, inventory, data);
                    })
                    .error(function(data, status) {
                        ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
                            msg: 'Call to ' + inventory.related.inventory_sources + ' failed. GET returned status: ' + status
                        });
                    });
            }
        }
    };

    $scope.showHostSummary = function(event, id) {
        var url, inventory;
        if (!Empty(id)) {
            inventory = Find({ list: $scope.inventories, key: 'id', val: id });
            if (inventory.total_hosts > 0) {
                Wait('start');
                url = GetBasePath('jobs') + "?type=job&inventory=" + id + "&failed=";
                url += (inventory.has_active_failures) ? 'true' : "false";
                url += "&order_by=-finished&page_size=5";
                Rest.setUrl(url);
                Rest.get()
                    .success( function(data) {
                        $scope.$emit('HostSummaryReady', event, data);
                    })
                    .error( function(data, status) {
                        ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
                            msg: 'Call to ' + url + ' failed. GET returned: ' + status
                        });
                    });
            }
        }
    };

    $scope.viewJob = function(url) {

        // Pull the id out of the URL
        var id = url.replace(/^\//, '').split('/')[3];

        $state.go('inventorySyncStdout', {id: id});

    };

    $scope.addInventory = function () {
        $state.go('inventories.add');
    };

    $scope.editInventory = function (id) {
        $state.go('inventories.edit', {inventory_id: id});
    };

    $scope.manageInventory = function(id){
      $location.path($location.path() + '/' + id + '/manage');
    };

    $scope.deleteInventory = function (id, name) {

        var action = function () {
            var url = defaultUrl + id + '/';
            Wait('start');
            $('#prompt-modal').modal('hide');
            Rest.setUrl(url);
            Rest.destroy()
                .success(function () {
                    if (parseInt($state.params.inventory_id) === id) {
                        $state.go("^", null, {reload: true});
                    } else {
                        $scope.search(list.iterator);
                    }
                })
                .error(function (data, status) {
                    ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
                        msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
                    });
                });
        };

        Prompt({
            hdr: 'Delete',
            body: '
Are you sure you want to delete the inventory below?

' + $filter('sanitize')(name) + '
',
            action: action,
            actionText: 'DELETE'
        });
    };

    $scope.lookupOrganization = function (organization_id) {
        Rest.setUrl(GetBasePath('organizations') + organization_id + '/');
        Rest.get()
            .success(function (data) {
                return data.name;
            });
    };

    // Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status
    $scope.viewJobs = function (id) {
        $location.url('/jobs/?inventory__int=' + id);
    };

    $scope.viewFailedJobs = function (id) {
        $location.url('/jobs/?inventory__int=' + id + '&status=failed');
    };
}

export default ['$scope', '$rootScope', '$location', '$log',
    '$stateParams', '$compile', '$filter', 'sanitizeFilter', 'Rest', 'Alert', 'InventoryList',
    'generateList', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller',
    'ClearScope', 'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty', '$state', InventoriesList];
<commit_msg>Added sanitize filter to other name instances<commit_after>/*************************************************
 * Copyright (c) 2016 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

/**
 * @ngdoc function
 * @name controllers.function:Inventories
 * @description This controller's for the Inventory page
 */

function InventoriesList($scope, $rootScope, $location, $log,
    $stateParams, $compile, $filter, sanitizeFilter, Rest, Alert, InventoryList,
    generateList, Prompt, SearchInit, PaginateInit, ReturnToCaller,
    ClearScope, ProcessErrors, GetBasePath, Wait,
    Find, Empty, $state) {

    var list = InventoryList,
        defaultUrl = GetBasePath('inventory') + ($stateParams.status === 'sync-failed' ? '?not__inventory_sources_with_failures=0' : ''),
        view = generateList,
        paths = $location.path().replace(/^\//, '').split('/'),
        mode = (paths[0] === 'inventories') ? 'edit' : 'select';

    function ellipsis(a) {
        if (a.length > 20) {
            return a.substr(0,20) + '...';
        }
        return a;
    }

    function attachElem(event, html, title) {
        var elem = $(event.target).parent();
        try {
            elem.tooltip('hide');
            elem.popover('destroy');
        }
        catch(err) {
            //ignore
        }
        $('.popover').each(function() {
            // remove lingering popover
. Seems to be a bug in TB3 RC1
            $(this).remove();
        });
        $('.tooltip').each( function() {
            // close any lingering tool tipss
            $(this).hide();
        });
        elem.attr({
            "aw-pop-over": html,
            "data-popover-title": title,
            "data-placement": "right" });
        $compile(elem)($scope);
        elem.on('shown.bs.popover', function() {
            $('.popover').each(function() {
                $compile($(this))($scope);  //make nested directives work!
            });
            $('.popover-content, .popover-title').click(function() {
                elem.popover('hide');
            });
        });
        elem.popover('show');
    }

    view.inject(InventoryList, { mode: mode, scope: $scope });
    $rootScope.flashMessage = null;

    SearchInit({
        scope: $scope,
        set: 'inventories',
        list: list,
        url: defaultUrl
    });

    PaginateInit({
        scope: $scope,
        list: list,
        url: defaultUrl
    });

    if ($stateParams.name) {
        $scope[InventoryList.iterator + 'InputDisable'] = false;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.name;
        $scope[InventoryList.iterator + 'SearchField'] = 'name';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.name.label;
        $scope[InventoryList.iterator + 'SearchSelectValue'] = null;
    }

    if ($stateParams.has_active_failures) {
        $scope[InventoryList.iterator + 'InputDisable'] = true;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.has_active_failures;
        $scope[InventoryList.iterator + 'SearchField'] = 'has_active_failures';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_active_failures.label;
        $scope[InventoryList.iterator + 'SearchSelectValue'] = ($stateParams.has_active_failures === 'true') ? {
            value: 1
        } : {
            value: 0
        };
    }

    if ($stateParams.has_inventory_sources) {
        $scope[InventoryList.iterator + 'InputDisable'] = true;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.has_inventory_sources;
        $scope[InventoryList.iterator + 'SearchField'] = 'has_inventory_sources';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_inventory_sources.label;
        $scope[InventoryList.iterator + 'SearchSelectValue'] = ($stateParams.has_inventory_sources === 'true') ? {
            value: 1
        } : {
            value: 0
        };
    }

    if ($stateParams.inventory_sources_with_failures) {
        // pass a value of true, however this field actually contains an integer value
        $scope[InventoryList.iterator + 'InputDisable'] = true;
        $scope[InventoryList.iterator + 'SearchValue'] = $stateParams.inventory_sources_with_failures;
        $scope[InventoryList.iterator + 'SearchField'] = 'inventory_sources_with_failures';
        $scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.inventory_sources_with_failures.label;
        $scope[InventoryList.iterator + 'SearchType'] = 'gtzero';
    }

    $scope.search(list.iterator);

    if ($scope.removePostRefresh) {
        $scope.removePostRefresh();
    }
    $scope.removePostRefresh = $scope.$on('PostRefresh', function () {
        //If we got here by deleting an inventory, stop the spinner and cleanup events
        Wait('stop');
        try {
            $('#prompt-modal').modal('hide');
        }
        catch(e) {
            // ignore
        }
        $scope.inventories.forEach(function(inventory, idx) {
            $scope.inventories[idx].launch_class = "";
            if (inventory.has_inventory_sources) {
                if (inventory.inventory_sources_with_failures > 0) {
                    $scope.inventories[idx].syncStatus = 'error';
                    $scope.inventories[idx].syncTip = inventory.inventory_sources_with_failures + ' groups with sync failures. Click for details';
                }
                else {
                    $scope.inventories[idx].syncStatus = 'successful';
                    $scope.inventories[idx].syncTip = 'No inventory sync failures. Click for details.';
                }
            }
            else {
                $scope.inventories[idx].syncStatus = 'na';
                $scope.inventories[idx].syncTip = 'Not configured for inventory sync.';
                $scope.inventories[idx].launch_class = "btn-disabled";
            }
            if (inventory.has_active_failures) {
                $scope.inventories[idx].hostsStatus = 'error';
                $scope.inventories[idx].hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.';
            }
            else if (inventory.total_hosts) {
                $scope.inventories[idx].hostsStatus = 'successful';
                $scope.inventories[idx].hostsTip = 'No hosts with failures. Click for details.';
            }
            else {
                $scope.inventories[idx].hostsStatus = 'none';
                $scope.inventories[idx].hostsTip = 'Inventory contains 0 hosts.';
            }
        });
    });

    if ($scope.removeRefreshInventories) {
        $scope.removeRefreshInventories();
    }
    $scope.removeRefreshInventories = $scope.$on('RefreshInventories', function () {
        // Reflect changes after inventory properties edit completes
        $scope.search(list.iterator);
    });

    if ($scope.removeHostSummaryReady) {
        $scope.removeHostSummaryReady();
    }
    $scope.removeHostSummaryReady = $scope.$on('HostSummaryReady', function(e, event, data) {

        var html, title = "Recent Jobs";
        Wait('stop');
        if (data.count > 0) {
            html = "
\n";
            html += "
\n";
            html += "
";
            html += "Status	";
            html += "Finished	";
            html += "Name	";
            html += "
\n";
            html += "
\n";
            html += "
\n";

            data.results.forEach(function(row) {
                html += "
\n";
                html += "	\n";
                html += "" + ($filter('longDate')(row.finished)).replace(/ /,'
') + "	";
                html += "" + $filter('sanitize')(ellipsis(row.name)) + "	";
                html += "
\n";
            });
            html += "
\n";
            html += "
\n";
        }
        else {
            html = "
No recent job data available for this inventory.
\n";
        }
        attachElem(event, html, title);
    });

    if ($scope.removeGroupSummaryReady) {
        $scope.removeGroupSummaryReady();
    }
    $scope.removeGroupSummaryReady = $scope.$on('GroupSummaryReady', function(e, event, inventory, data) {
        var html, title;

        Wait('stop');

        // Build the html for our popover
        html = "
\n";
        html += "
\n";
        html += "
";
        html += "Status	";
        html += "Last Sync	";
        html += "Group	";
        html += "
";
        html += "
\n";
        html += "
\n";
        data.results.forEach( function(row) {
            if (row.related.last_update) {
                html += "
";
                html += `	`;
                html += "" + ($filter('longDate')(row.last_updated)).replace(/ /,'
') + "	";
                html += "" + $filter('sanitize')(ellipsis(row.summary_fields.group.name)) + "	";
                html += "
\n";
            }
            else {
                html += "
";
                html += "	";
                html += "NA	";
                html += "" + $filter('sanitize')(ellipsis(row.summary_fields.group.name)) + "	";
                html += "
\n";
            }
        });
        html += "
\n";
        html += "
\n";
        title = "Sync Status";
        attachElem(event, html, title);
    });

    $scope.showGroupSummary = function(event, id) {
        var inventory;
        if (!Empty(id)) {
            inventory = Find({ list: $scope.inventories, key: 'id', val: id });
            if (inventory.syncStatus !== 'na') {
                Wait('start');
                Rest.setUrl(inventory.related.inventory_sources + '?or__source=ec2&or__source=rax&order_by=-last_job_run&page_size=5');
                Rest.get()
                    .success(function(data) {
                        $scope.$emit('GroupSummaryReady', event, inventory, data);
                    })
                    .error(function(data, status) {
                        ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
                            msg: 'Call to ' + inventory.related.inventory_sources + ' failed. GET returned status: ' + status
                        });
                    });
            }
        }
    };

    $scope.showHostSummary = function(event, id) {
        var url, inventory;
        if (!Empty(id)) {
            inventory = Find({ list: $scope.inventories, key: 'id', val: id });
            if (inventory.total_hosts > 0) {
                Wait('start');
                url = GetBasePath('jobs') + "?type=job&inventory=" + id + "&failed=";
                url += (inventory.has_active_failures) ? 'true' : "false";
                url += "&order_by=-finished&page_size=5";
                Rest.setUrl(url);
                Rest.get()
                    .success( function(data) {
                        $scope.$emit('HostSummaryReady', event, data);
                    })
                    .error( function(data, status) {
                        ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
                            msg: 'Call to ' + url + ' failed. GET returned: ' + status
                        });
                    });
            }
        }
    };

    $scope.viewJob = function(url) {

        // Pull the id out of the URL
        var id = url.replace(/^\//, '').split('/')[3];

        $state.go('inventorySyncStdout', {id: id});

    };

    $scope.addInventory = function () {
        $state.go('inventories.add');
    };

    $scope.editInventory = function (id) {
        $state.go('inventories.edit', {inventory_id: id});
    };

    $scope.manageInventory = function(id){
      $location.path($location.path() + '/' + id + '/manage');
    };

    $scope.deleteInventory = function (id, name) {

        var action = function () {
            var url = defaultUrl + id + '/';
            Wait('start');
            $('#prompt-modal').modal('hide');
            Rest.setUrl(url);
            Rest.destroy()
                .success(function () {
                    if (parseInt($state.params.inventory_id) === id) {
                        $state.go("^", null, {reload: true});
                    } else {
                        $scope.search(list.iterator);
                    }
                })
                .error(function (data, status) {
                    ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
                        msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
                    });
                });
        };

        Prompt({
            hdr: 'Delete',
            body: '
Are you sure you want to delete the inventory below?

' + $filter('sanitize')(name) + '
',
            action: action,
            actionText: 'DELETE'
        });
    };

    $scope.lookupOrganization = function (organization_id) {
        Rest.setUrl(GetBasePath('organizations') + organization_id + '/');
        Rest.get()
            .success(function (data) {
                return data.name;
            });
    };

    // Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status
    $scope.viewJobs = function (id) {
        $location.url('/jobs/?inventory__int=' + id);
    };

    $scope.viewFailedJobs = function (id) {
        $location.url('/jobs/?inventory__int=' + id + '&status=failed');
    };
}

export default ['$scope', '$rootScope', '$location', '$log',
    '$stateParams', '$compile', '$filter', 'sanitizeFilter', 'Rest', 'Alert', 'InventoryList',
    'generateList', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller',
    'ClearScope', 'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty', '$state', InventoriesList];
<|endoftext|>


<commit_before>import Post from '../../models/post';
import serialize from '../../serializers/post';

export default (params, res, app, user) =>
{
	let limit = params.limit;

	// Init 'text' parameter
	if (limit !== undefined && limit !== null) {
		limit = parseInt(limit, 10);

		if (limit < 1) {
			return res(400, 'invalid-limit-range');
		} else if (limit > 100) {
			return res(400, 'invalid-limit-range');
		}
	} else {
		limit = 10;
	}

	let sinceId = params['since-id'] || null;
	let maxId = params['max-id'] || null;

	// 自分がフォローしているユーザーの関係を取得
	UserFollowing
	.find({follower: user.id})
	.lean()
	.exec((followingFindErr, following) => {
		if (followingFindErr) {
			return res(500, followingFindErr);
		}

		// 自分と自分がフォローしているユーザーのIDのリストを生成
		const followingIds = following.length !== 0
			? [...following.map(follow => follow.followee), user.id]
			: [user.id];

		// タイムライン取得用のクエリを生成
		const sort = {created_at: -1};
		const query = {
			user: { $in: followingIds }
		};
		if (sinceId !== null) {
			sort.created_at = 1;
			query.cursor = {$gt: sinceId};
		} else if (maxId !== null) {
			query.cursor = {$lt: maxId};
		}

		// クエリを発行してタイムラインを取得
		Post
		.find(query)
		.sort(sort)
		.limit(limit)
		.lean()
		.exec((err, timeline) => {
			if (err) {
				return res(500, err);
			} else if (timeline.length === 0) {
				return res([]);
			}

			// send
			res(timeline.map(async (post) => {
				return await serialize(post);
			}));
		});
	});
};
<commit_msg>Improve readavility<commit_after>import Post from '../../models/post';
import serialize from '../../serializers/post';

export default async (params, res, app, user) =>
{
	let limit = params.limit;

	// Init 'text' parameter
	if (limit !== undefined && limit !== null) {
		limit = parseInt(limit, 10);

		if (limit < 1) {
			return res(400, 'invalid-limit-range');
		} else if (limit > 100) {
			return res(400, 'invalid-limit-range');
		}
	} else {
		limit = 10;
	}

	let sinceId = params['since-id'] || null;
	let maxId = params['max-id'] || null;

	// 自分がフォローしているユーザーの関係を取得
	const following = await UserFollowing
		.find({follower: user.id})
		.lean()
		.exec();

	// 自分と自分がフォローしているユーザーのIDのリストを生成
	const followingIds = following.length !== 0
		? [...following.map(follow => follow.followee), user.id]
		: [user.id];

	// タイムライン取得用のクエリを生成
	const sort = {created_at: -1};
	const query = {
		user: { $in: followingIds }
	};
	if (sinceId !== null) {
		sort.created_at = 1;
		query.cursor = {$gt: sinceId};
	} else if (maxId !== null) {
		query.cursor = {$lt: maxId};
	}

	// クエリを発行してタイムラインを取得
	Post
	.find(query)
	.sort(sort)
	.limit(limit)
	.lean()
	.exec((err, timeline) => {
		if (err) {
			return res(500, err);
		} else if (timeline.length === 0) {
			return res([]);
		}

		// send
		res(timeline.map(async (post) => {
			return await serialize(post);
		}));
	});
};
<|endoftext|>


<commit_before>module.exports = function(grunt)
{
	var _ = grunt.util._,
		log = grunt.log,
		verbose = grunt.verbose,
		fs = require('fs'),
		f = require('util').format;

	grunt.registerMultiTask(
		'audiosprite',
		'Combine the uncompressed audio into an audiosprite',
		function()
		{
			var data = this.data,
				output = data.output || "output",
				ogg_to_oga = data.ogg_to_oga || true,
				cwd = data.cwd || process.cwd(),
				callback = _.isFunction(data.callback) ? data.callback : function() {},
				files = data.files,
				cmd = [__dirname + '/../node_modules/.bin/audiosprite'],
				done = this.async();

			// These are the acceptable audiosprite arguemnts
			var validKeys = [
				'output',
				'priority',
				'export',
				'log',
				'loop',
				'autoplay',
				'silence',
				'samplerate',
				'channels',
				'rawparts',
				'bitrate'
			];

			// These can have arrays as values
			var validArrayValues = [
				'loop',
				'export'
			];

			// These are the valid other options for this task
			var otherKeys = [
				'cwd',
				'callback',
				'files',
				'ogg_to_oga'
			];

			// Convert the data input into arguments for audiosprite
			_.each(data, function (value, key, list) {
				if (_.contains(validKeys, key)) {
					if (_.contains(validArrayValues, key) && _.isArray(value)) {
						value = value.join(',');
					}
					if (!_.isString(value) && !_.isNumber(value)) {
						log.error("The audiosprite option '" + key + "' cannot be a " + (typeof key));
					} else {
						cmd.push('--'+key, value);
					}
				} else if (_.contains(otherKeys, key)) {
					// Ignore these
				} else {
					log.error("The audiosprite task doesn't accept '" + key + "' argument");
				}
			});

			// Check for files, which is required!
			if (!files)
			{
				log.error("Source files audio must be defined for the audiosprite");
				return done(false);
			}

			// Convert files into an array
			files = _.isArray(files) ? files.join(' ') : files;

			var cp = require('child_process');
			child = cp.exec(
				cmd.join(' ') + ' ' + files,
				{ cwd: cwd },
				callback
			);

			child.stdout.on('data', function (d) { log.write(d); });
			child.stderr.on('data', function (d) { log.error(d); });

			// Catches failing to execute the command at all (eg spawn ENOENT),
			// since in that case an 'exit' event will not be emitted.
			child.on('error', function (err) {
				log.error(f('Failed with: %s', err));
				done(false);
			});

			child.on('exit', function (code) {
				if (code) {
					log.error(f('Exited with code: %d.', code));
					return done(false);
				}
				verbose.ok(f('Exited with code: %d.', code));

				if (ogg_to_oga || data.cwd)
				{
					var json = grunt.file.read(cwd + '/' + output + '.json');
					if (ogg_to_oga)
					{
						fs.rename(cwd + '/' + output +'.ogg', cwd + '/' + output +'.oga');
						json = json.replace(/\.ogg/g, '.oga');
					}
					if (data.cwd) json = json.replace(/\.ogg/g, '.oga');
					grunt.file.write(cwd + '/' + output + '.json', json);
				}
				done();
			});
		}
	);
};
<commit_msg>Added "input" field that gets wildcards expanded.<commit_after>module.exports = function(grunt)
{
	var _ = grunt.util._,
		log = grunt.log,
		verbose = grunt.verbose,
		fs = require('fs'),
		f = require('util').format;

	grunt.registerMultiTask(
		'audiosprite',
		'Combine the uncompressed audio into an audiosprite',
		function()
		{
			var data = this.data,
				input = grunt.file.expand(data.input)
				output = data.output || "output",
				ogg_to_oga = data.ogg_to_oga || true,
				cwd = data.cwd || process.cwd(),
				callback = _.isFunction(data.callback) ? data.callback : function() {},
				files = data.files,
				cmd = [__dirname + '/../node_modules/.bin/audiosprite'],
				done = this.async();

			// These are the acceptable audiosprite arguemnts
			var validKeys = [
				'output',
				'priority',
				'export',
				'log',
				'loop',
				'autoplay',
				'silence',
				'samplerate',
				'channels',
				'rawparts',
				'bitrate'
			];

			// These can have arrays as values
			var validArrayValues = [
				'loop',
				'export'
			];

			// These are the valid other options for this task
			var otherKeys = [
				'cwd',
				'callback',
				'files',
				'input',
				'ogg_to_oga'
			];

			// Convert the data input into arguments for audiosprite
			_.each(data, function (value, key, list) {
				if (_.contains(validKeys, key)) {
					if (_.contains(validArrayValues, key) && _.isArray(value)) {
						value = value.join(',');
					}
					if (!_.isString(value) && !_.isNumber(value)) {
						log.error("The audiosprite option '" + key + "' cannot be a " + (typeof key));
					} else {
						cmd.push('--'+key, value);
					}
				} else if (_.contains(otherKeys, key)) {
					// Ignore these
				} else {
					log.error("The audiosprite task doesn't accept '" + key + "' argument");
				}
			});

			// Check for files, which is required!
			files = input || files
			if (!files)
			{
				log.error("Source files audio must be defined for the audiosprite");
				return done(false);
			}

			// Convert files into an array
			files = _.isArray(files) ? files.join(' ') : files;

			var cp = require('child_process');
			child = cp.exec(
				cmd.join(' ') + ' ' + files,
				{ cwd: cwd },
				callback
			);

			child.stdout.on('data', function (d) { log.write(d); });
			child.stderr.on('data', function (d) { log.error(d); });

			// Catches failing to execute the command at all (eg spawn ENOENT),
			// since in that case an 'exit' event will not be emitted.
			child.on('error', function (err) {
				log.error(f('Failed with: %s', err));
				done(false);
			});

			child.on('exit', function (code) {
				if (code) {
					log.error(f('Exited with code: %d.', code));
					return done(false);
				}
				verbose.ok(f('Exited with code: %d.', code));

				if (ogg_to_oga || data.cwd)
				{
					var json = grunt.file.read(cwd + '/' + output + '.json');
					if (ogg_to_oga)
					{
						fs.rename(cwd + '/' + output +'.ogg', cwd + '/' + output +'.oga');
						json = json.replace(/\.ogg/g, '.oga');
					}
					if (data.cwd) json = json.replace(/\.ogg/g, '.oga');
					grunt.file.write(cwd + '/' + output + '.json', json);
				}
				done();
			});
		}
	);
};
<|endoftext|>


<commit_before>/**
 * Created by jack on 14-9-22.
 */

Ext.define('EqimPrj.view.eqimmain.ManualSendMsgAutoWin' ,{
    extend: 'Ext.window.Window',
    alias : 'widget.manualsendmsgautowin',
    requires: [
    ],
    initComponent: function() {
        var required = '*';
        Ext.apply(this, {
            title: '新增',
            height: 370,
            width: 460,
            closeAction : 'hide',
            modal:true,
            resizable:false,
            layout: 'fit',
            items: {
                xtype: 'form',
                layout: {
                    type: 'vbox',
                    align: 'stretch'
                },
                border: false,
                bodyPadding: 10,
                //xtype: 'fieldset',

                fieldDefaults: {
                    labelAlign: 'top',
                    labelWidth: 100,
                    labelStyle: 'font-weight:bold'
                },

                items: [

                    {
                        xtype: 'textfield',
                        name: 'title',
                        itemId:'title',
                        required:true,
                        allowBlank:false,
                        disabled:true,
                        afterLabelTextTpl: required,
                        fieldLabel: '发送标题'
                    },{
                        xtype: 'textarea',
                        name: 'content',
                        itemId:'content',
                        required:true,
                        listeners: {
                            change:function(obj,v){
                                var win=obj.up('window');
                                ischar= v.indexOf("(");
                                var arr=ischar>0?v.split("(")[0].split(":"):v.split("（")[0].split(":");
                                var data=win.data;
                                var str=arr[arr.length-1] +"发生"+data.M.toFixed(1)+"级左右地震。";
                                var title=win.down('#title');

                                //var titlecontent=Ext.Date.format(new Date(data.time),'m月d日H时i分')+data.location+"发生"+data.M.toFixed(1)+"级左右地震。";
                                title.setValue(str);
                            }
                        },
                        allowBlank:false,
                        afterLabelTextTpl: required,
                        fieldLabel: '发送内容'
                    },
                    {
                        xtype:'fieldset',
                        title: '发送方式',
                        layout: {
                            type: 'hbox'
                        },
                        items:[
                            {
                                xtype:'checkbox',
                                boxLabel: '短信',

                                checked: true,
                                name: 'sendway',
                                inputValue: '0'
                            }, {
                                xtype:'checkbox',
                                boxLabel: '微博',

                                checked: true,
                                name: 'sendway',
                                inputValue: '1'
                            }, {
                                xtype:'checkbox',
                                checked: false,
                                listeners: {
                                    change:function(obj,v){
                                        var win=obj.up('window');
                                        var title=win.down('#title');
                                        var data=win.data;
                                        var titlecontent=Ext.Date.format(new Date(data.time),'m月d日H时i分')+data.location+"发生"+data.M.toFixed(1)+"级地震。";

                                        title.setValue(titlecontent);
                                        //win.titlecontent=titlecontent;
                                        if(v){

                                           title.enable();
                                        }else{
                                            title.disable();
                                        }

                                    }
                                },
                                boxLabel: '网站',
                                name: 'sendway',
                                inputValue: '2'
                            }
                        ]
                    },{
                        xtype: 'combobox',
                        required:true,
                        allowBlank:false,
                        itemId:'groupscomb',
                        queryMode: 'local',
                        /*multiSelect: false,
                        autoSelect:true,*/
                        forceSelection:true,
                        afterLabelTextTpl: required,
                        listeners:{
                            'change': function (rec){
                                this.fireEvent('onselectfunc', rec,this)

                            }
                        },
                        store:Ext.create('Ext.data.Store', {
                            fields: ['value', 'name'],
                            autoLoad: true,
                            data : (function (){
                                var arr=eval(localStorage.groupsvalue);
                                var result=[];
                                for(var i=0;i<arr.length;i++){
                                    result.push({name:arr[i],value:arr[i]});
                                }
                                return result;
                            })()
                        }),
                        valueField: 'value',
                        displayField: 'name',
                        fieldLabel: '分组',
                        name: 'groups'
                    }

                ],
                buttons: [
                    {
                        text: '取消',
                        handler: function () {
                            this.up('window').hide();
                        }
                    } ,
                    {
                        text: '发送',
                        action: 'send'

                    }
                ],
                border: false

            }

        });
        this.callParent(arguments);
    }

});

<commit_msg>jack commit<commit_after>/**
 * Created by jack on 14-9-22.
 */

Ext.define('EqimPrj.view.eqimmain.ManualSendMsgAutoWin' ,{
    extend: 'Ext.window.Window',
    alias : 'widget.manualsendmsgautowin',
    requires: [
    ],
    initComponent: function() {
        var required = '*';
        Ext.apply(this, {
            title: '新增',
            height: 370,
            width: 460,
            closeAction : 'hide',
            modal:true,
            resizable:false,
            layout: 'fit',
            items: {
                xtype: 'form',
                layout: {
                    type: 'vbox',
                    align: 'stretch'
                },
                border: false,
                bodyPadding: 10,
                //xtype: 'fieldset',

                fieldDefaults: {
                    labelAlign: 'top',
                    labelWidth: 100,
                    labelStyle: 'font-weight:bold'
                },

                items: [

                    {
                        xtype: 'textfield',
                        name: 'title',
                        itemId:'title',
                        required:true,
                        allowBlank:false,
                        disabled:true,
                        afterLabelTextTpl: required,
                        fieldLabel: '发送标题'
                    },{
                        xtype: 'textarea',
                        name: 'content',
                        itemId:'content',
                        required:true,
                        listeners: {
                            change:function(obj,v){
                                var win=obj.up('window');
                                ischar= v.indexOf("(");
                                var arr=ischar>0?v.split("(")[0].split(":"):v.split("（")[0].split(":");
                                var data=win.data;
                                var str=arr[arr.length-1] +"发生"+data.M.toFixed(1)+"级地震。"; //左右
                                var title=win.down('#title');

                                //var titlecontent=Ext.Date.format(new Date(data.time),'m月d日H时i分')+data.location+"发生"+data.M.toFixed(1)+"级左右地震。";
                                title.setValue(str);
                            }
                        },
                        allowBlank:false,
                        afterLabelTextTpl: required,
                        fieldLabel: '发送内容'
                    },
                    {
                        xtype:'fieldset',
                        title: '发送方式',
                        layout: {
                            type: 'hbox'
                        },
                        items:[
                            {
                                xtype:'checkbox',
                                boxLabel: '短信',

                                checked: true,
                                name: 'sendway',
                                inputValue: '0'
                            }, {
                                xtype:'checkbox',
                                boxLabel: '微博',

                                checked: true,
                                name: 'sendway',
                                inputValue: '1'
                            }, {
                                xtype:'checkbox',
                                checked: false,
                                listeners: {
                                    change:function(obj,v){
                                        var win=obj.up('window');
                                        var title=win.down('#title');
                                        var data=win.data;
                                        var titlecontent=Ext.Date.format(new Date(data.time),'m月d日H时i分')+data.location+"发生"+data.M.toFixed(1)+"级地震。";

                                        title.setValue(titlecontent);
                                        //win.titlecontent=titlecontent;
                                        if(v){

                                           title.enable();
                                        }else{
                                            title.disable();
                                        }

                                    }
                                },
                                boxLabel: '网站',
                                name: 'sendway',
                                inputValue: '2'
                            }
                        ]
                    },{
                        xtype: 'combobox',
                        required:true,
                        allowBlank:false,
                        itemId:'groupscomb',
                        queryMode: 'local',
                        /*multiSelect: false,
                        autoSelect:true,*/
                        forceSelection:true,
                        afterLabelTextTpl: required,
                        listeners:{
                            'change': function (rec){
                                this.fireEvent('onselectfunc', rec,this)

                            }
                        },
                        store:Ext.create('Ext.data.Store', {
                            fields: ['value', 'name'],
                            autoLoad: true,
                            data : (function (){
                                var arr=eval(localStorage.groupsvalue);
                                var result=[];
                                for(var i=0;i<arr.length;i++){
                                    result.push({name:arr[i],value:arr[i]});
                                }
                                return result;
                            })()
                        }),
                        valueField: 'value',
                        displayField: 'name',
                        fieldLabel: '分组',
                        name: 'groups'
                    }

                ],
                buttons: [
                    {
                        text: '取消',
                        handler: function () {
                            this.up('window').hide();
                        }
                    } ,
                    {
                        text: '发送',
                        action: 'send'

                    }
                ],
                border: false

            }

        });
        this.callParent(arguments);
    }

});

<|endoftext|>


<commit_before>/*
 * grunt-include-resources
 * https://github.com/dsuckau/grunt-include-resources
 *
 * Copyright (c) 2014 Denis Suckau
 * Licensed under the MIT license.
 */

module.exports = function (grunt) {

    'use strict';

    grunt.registerMultiTask('include_resources', 'Include resources into HTML files.', function() {

        // Default options
        var options = this.options({
                prefix: '<!-- include: ',
                suffix: ' -->',
                css: {},
                js: {}
            }),

            // Regular expression to match include directives
            re = new RegExp(
                options.prefix +
                '({[\\s\\S]*?})' +
                options.suffix,
                'g'
            );

        this.files.forEach(function (file) {

            // Merge all source files
            var src = file.src.filter(function (filepath) {
                    if (!grunt.file.exists(filepath)) {
                        grunt.log.warn('Source file "' + filepath + '" not found.');
                        return false;
                    }
                    return true;
                })
                .map(grunt.file.read)
                .join(grunt.util.normalizelf(grunt.util.linefeed)),
                includes = [],
                match;

            // Match all include directives
            while (match = re.exec(src)) {
                includes.push({
                    directive: match[0],
                    config: JSON.parse(match[1])
                });
            }

            includes.forEach(function (include) {

                var id = include.config.id,
                    type = include.config.type,
                    data = '',
                    filepath,
                    content;

                // Identifier found in options
                if (id in options[type]) {

                    filepath = options[type][id];

                    // Resource file found
                    if (grunt.file.exists(filepath)) {

                        // Read resource file content
                        content = grunt.file.read(filepath);

                        // JavaScript
                        if (type === 'js') {
                            data = [
                                '<script type="text/javascript">',
                                content,
                                '</script>'
                            ].join(grunt.util.normalizelf(grunt.util.linefeed));

                        // CSS
                        } else {
                            data = [
                                '<style type="text/css">',
                                content,
                                '</style>'
                            ].join(grunt.util.normalizelf(grunt.util.linefeed));
                        }

                    // Resource file not found
                    } else {
                        grunt.log.warn('Resource file "' + filepath + '" not found.');
                    }

                // Identifier not found in options
                } else {
                    grunt.log.warn('Identifier "' + id + '" with type "' + type + '" not found.');
                }

                // Replace include directive
                src = src.replace(include.directive, data);

            });

            // Write destination file
            grunt.file.write(file.dest, src);
            grunt.log.writeln('File "' + file.dest + '" created.');

        });

    });

};<commit_msg>use a function as second param in src.replace() to avoid replacing of potential back references<commit_after>/*
 * grunt-include-resources
 * https://github.com/dsuckau/grunt-include-resources
 *
 * Copyright (c) 2014 Denis Suckau
 * Licensed under the MIT license.
 */

module.exports = function (grunt) {

    'use strict';

    grunt.registerMultiTask('include_resources', 'Include resources into HTML files.', function() {

        // Default options
        var options = this.options({
                prefix: '<!-- include: ',
                suffix: ' -->',
                css: {},
                js: {}
            }),

            // Regular expression to match include directives
            re = new RegExp(
                options.prefix +
                '({[\\s\\S]*?})' +
                options.suffix,
                'g'
            );

        this.files.forEach(function (file) {

            // Merge all source files
            var src = file.src.filter(function (filepath) {
                    if (!grunt.file.exists(filepath)) {
                        grunt.log.warn('Source file "' + filepath + '" not found.');
                        return false;
                    }
                    return true;
                })
                .map(grunt.file.read)
                .join(grunt.util.normalizelf(grunt.util.linefeed)),
                includes = [],
                match;

            // Match all include directives
            while (match = re.exec(src)) {
                includes.push({
                    directive: match[0],
                    config: JSON.parse(match[1])
                });
            }

            includes.forEach(function (include) {

                var id = include.config.id,
                    type = include.config.type,
                    data = '',
                    filepath,
                    content;

                // Identifier found in options
                if (id in options[type]) {

                    filepath = options[type][id];

                    // Resource file found
                    if (grunt.file.exists(filepath)) {

                        // Read resource file content
                        content = grunt.file.read(filepath);

                        // JavaScript
                        if (type === 'js') {
                            data = [
                                '<script type="text/javascript">',
                                content,
                                '</script>'
                            ].join(grunt.util.normalizelf(grunt.util.linefeed));

                        // CSS
                        } else {
                            data = [
                                '<style type="text/css">',
                                content,
                                '</style>'
                            ].join(grunt.util.normalizelf(grunt.util.linefeed));
                        }

                    // Resource file not found
                    } else {
                        grunt.log.warn('Resource file "' + filepath + '" not found.');
                    }

                // Identifier not found in options
                } else {
                    grunt.log.warn('Identifier "' + id + '" with type "' + type + '" not found.');
                }

                // Replace include directive
                src = src.replace(include.directive, function () {
                    return data;
                });

            });

            // Write destination file
            grunt.file.write(file.dest, src);
            grunt.log.writeln('File "' + file.dest + '" created.');

        });

    });

};<|endoftext|>


<commit_before>// Probe.js (c) 2010-2013 Loren West and other contributors
// May be freely distributed under the MIT license.
// For further details and documentation:
// http://lorenwest.github.com/monitor-min
(function(root){

  // Module loading
  var Monitor = root.Monitor || require('./Monitor'),
      log = Monitor.getLogger('Probe'),
      stat = Monitor.getStatLogger('Probe'),
      Cron = Monitor.Cron, _ = Monitor._, Backbone = Monitor.Backbone;

  /**
  * A software device used to expose real time data to monitors
  *
  * This is the base class from which all probe implementations extend.
  *
  * In order to send probe data to monitors, probe implementations simply set
  * their model data using ```set()```.  Those changes are detected and propagated
  * to all monitors of this probe, firing their change events.
  *
  * In order to allow remote probe control, probes need only provide a method
  * called ```{name}_control()```.  See the ```ping_control()``` method as an example,
  * and the ```Probe.onControl()``` method for more information.
  *
  * @class Probe
  * @extends Backbone.Model
  * @constructor
  * @param model - Initial data model.  Can be a JS object or another Model.
  *     @param model.id {String} The probe id.
  *       Assigned by the Router on probe instantiation.
  */
  var Probe = Monitor.Probe = Backbone.Model.extend({

    defaults: {
      id:  null
    },

    /**
    * Initialize the probe
    *
    * This is called on the probe during construction.  It contains
    * the probe initialization attributes and an option to make probe
    * construction asynchronous.
    *
    * Probe implementations can defer the initial response to the monitor until
    * the initial state is loaded.  This allows the callback on
    * ```Monitor.connect()```
    * to have the complete initial state of the probe when called.
    *
    * If the initial probe state cannot be determined in ```initialize```, it should
    * set the ```options.asyncInit``` option to ```true```, and call the
    * ```options.callback(error)``` once the initial state is determined.
    *
    *     // Asynchronous initialization
    *     options.asyncInit = true;
    *     var callback = options.callback
    *
    * If ```asyncInit``` is set to true, the ```callback``` must be called once
    * the initial state of the probe is known (or in an error condition).
    *
    *     // Set the initial state, and call the callback
    *     this.set(...);
    *     callback(null);
    *
    * See the ```initialize```
    * method of the FileProbe probe for an example.  It defers
    * returning the probe to the monitor until the initial file contents are loaded.
    *
    * @method initialize
    * @param attributes {Object} Initial probe attributes sent in from the Monitor
    * @param options {Object} Initialization options
    *     @param options.asyncInit {boolean} Set this to TRUE if the initial probe
    *         state can't be known immediately.
    *     @param options.callback {function(error)} The callback to call
    *         if asyncInit is set to true.  If an error is passed, the probe
    *         will not be used.
    */
    initialize: function(attributes, options) {
      var t = this;
      log.info('init', t.toJSON(), attributes, options);
    },

    /**
    * Release any resources consumed by this probe.
    *
    * This can be implemented by derived classes that need to be informed when
    * they are to be shut down.
    *
    * Probes that listen to events should use this method to remove their
    * event listeners.
    *
    * @method release
    */
    release: function(){
      var t = this;
      log.info('release', t.toJSON());
    },

    /**
    * Dispatch a control message to the appropriate control function.
    *
    * This is called when the
    * ```control()```
    * method of a monitor is called.
    * The name determines the method name called on the probe.
    *
    * The probe must implement a method with the name ```{name}_control()```,
    * and that method must accept two parameters - an input params and a callback.
    * The callback must be called, passing an optional error and response object.
    *
    * For example, if the probe supports a control with the name ```go```, then
    * all it needs to do is implement the ```go_control()``` method with the
    * proper signature.  See ```ping_control()``` for an example.
    *
    * @method onControl
    * @param name {String} Name of the control message.
    * @param [params] {Any} Input parameters specific to the control message.
    * @param [callback] {Function(error, response)} Called to send the message (or error) response.
    *

    *
error (Any) An object describing an error (null if no errors)

    *
response (Any) Response parameters specific to the control message.
    *

    */
    onControl: function(name, params, callback) {
      params = params || {};
      callback = callback || function(){};
      var t = this, controlFn = t[name + '_control'], errMsg;
      log.info('onControl', t.toJSON(), name, params);
      if (!controlFn) {return callback({msg:'No control function: ' + name});}
      try {
        controlFn.call(t, params, callback);
      } catch (e) {
        errMsg = 'Error calling control: ' + t.probeClass + ':' + name;
        console.error(errMsg, e);
        callback({msg:errMsg});
      }
    },

    /**
    * Respond to a ping control sent from a monitor
    *
    * @method ping_control
    * @param params {Object} Input parameters (not used)
    * @param callback {Function(error, response)} Called to send the message (or error) response.
    *

    *
error (Any) An object describing an error

    *
response (String) The string 'pong' is returned as the response

    *

    */
    ping_control: function(params, callback) {
      return callback(null, 'pong');
    }

  });

  // Register probe classes when loaded
  Probe.classes = {}; // key = name, data = class definition
  Probe.extend = function(params) {
    var t = this, probeClass = Backbone.Model.extend.apply(t, arguments);
    if (params.probeClass) {Probe.classes[params.probeClass] = probeClass;}
    return probeClass;
  };

  /**
  * Constructor for a list of Probe objects
  *
  *     var myList = new Probe.List(initialElements);
  *
  * @static
  * @method List
  * @param [items] {Array} Initial list items.  These can be raw JS objects or Probe data model objects.
  * @return {Backbone.Collection} Collection of Probe data model objects
  */
  Probe.List = Backbone.Collection.extend({model: Probe});

}(this));
<commit_msg>Better probe logging<commit_after>// Probe.js (c) 2010-2013 Loren West and other contributors
// May be freely distributed under the MIT license.
// For further details and documentation:
// http://lorenwest.github.com/monitor-min
(function(root){

  // Module loading
  var Monitor = root.Monitor || require('./Monitor'),
      log = Monitor.getLogger('Probe'),
      stat = Monitor.getStatLogger('Probe'),
      Cron = Monitor.Cron, _ = Monitor._, Backbone = Monitor.Backbone;

  /**
  * A software device used to expose real time data to monitors
  *
  * This is the base class from which all probe implementations extend.
  *
  * In order to send probe data to monitors, probe implementations simply set
  * their model data using ```set()```.  Those changes are detected and propagated
  * to all monitors of this probe, firing their change events.
  *
  * In order to allow remote probe control, probes need only provide a method
  * called ```{name}_control()```.  See the ```ping_control()``` method as an example,
  * and the ```Probe.onControl()``` method for more information.
  *
  * @class Probe
  * @extends Backbone.Model
  * @constructor
  * @param model - Initial data model.  Can be a JS object or another Model.
  *     @param model.id {String} The probe id.
  *       Assigned by the Router on probe instantiation.
  */
  var Probe = Monitor.Probe = Backbone.Model.extend({

    defaults: {
      id:  null
    },

    /**
    * Initialize the probe
    *
    * This is called on the probe during construction.  It contains
    * the probe initialization attributes and an option to make probe
    * construction asynchronous.
    *
    * Probe implementations can defer the initial response to the monitor until
    * the initial state is loaded.  This allows the callback on
    * ```Monitor.connect()```
    * to have the complete initial state of the probe when called.
    *
    * If the initial probe state cannot be determined in ```initialize```, it should
    * set the ```options.asyncInit``` option to ```true```, and call the
    * ```options.callback(error)``` once the initial state is determined.
    *
    *     // Asynchronous initialization
    *     options.asyncInit = true;
    *     var callback = options.callback
    *
    * If ```asyncInit``` is set to true, the ```callback``` must be called once
    * the initial state of the probe is known (or in an error condition).
    *
    *     // Set the initial state, and call the callback
    *     this.set(...);
    *     callback(null);
    *
    * See the ```initialize```
    * method of the FileProbe probe for an example.  It defers
    * returning the probe to the monitor until the initial file contents are loaded.
    *
    * @method initialize
    * @param attributes {Object} Initial probe attributes sent in from the Monitor
    * @param options {Object} Initialization options
    *     @param options.asyncInit {boolean} Set this to TRUE if the initial probe
    *         state can't be known immediately.
    *     @param options.callback {function(error)} The callback to call
    *         if asyncInit is set to true.  If an error is passed, the probe
    *         will not be used.
    */
    initialize: function(attributes, options) {
      var t = this;
      log.info('init', t.toJSON(), options);
    },

    /**
    * Release any resources consumed by this probe.
    *
    * This can be implemented by derived classes that need to be informed when
    * they are to be shut down.
    *
    * Probes that listen to events should use this method to remove their
    * event listeners.
    *
    * @method release
    */
    release: function(){
      var t = this;
      log.info('release', t.toJSON());
    },

    /**
    * Dispatch a control message to the appropriate control function.
    *
    * This is called when the
    * ```control()```
    * method of a monitor is called.
    * The name determines the method name called on the probe.
    *
    * The probe must implement a method with the name ```{name}_control()```,
    * and that method must accept two parameters - an input params and a callback.
    * The callback must be called, passing an optional error and response object.
    *
    * For example, if the probe supports a control with the name ```go```, then
    * all it needs to do is implement the ```go_control()``` method with the
    * proper signature.  See ```ping_control()``` for an example.
    *
    * @method onControl
    * @param name {String} Name of the control message.
    * @param [params] {Any} Input parameters specific to the control message.
    * @param [callback] {Function(error, response)} Called to send the message (or error) response.
    *

    *
error (Any) An object describing an error (null if no errors)

    *
response (Any) Response parameters specific to the control message.
    *

    */
    onControl: function(name, params, callback) {
      var t = this,
          controlFn = t[name + '_control'],
          startTime = Date.now(),
          errMsg,
          logId = 'onControl.' + t.probeClass + '.' + name;

      params = params || {};
      callback = callback || function(){};
      log.info(logId, t.get('id'), params);

      if (!controlFn) {
        errMsg = 'No control function: ' + name;
        log.error(logId, errMsg);
        return callback({msg: errMsg});
      }

      var whenDone = function(error) {
        if (error) {
          log.error(logId, error);
          return callback(error);
        }
        var duration = Date.now() - startTime;
        log.info(logId, duration);
        stat.time(t.logId, duration)
        callback.apply(null, arguments);
      };

      try {
        controlFn.call(t, params, whenDone);
      } catch (e) {
        errMsg = 'Error calling control: ' + t.probeClass + ':' + name;
        whenDone({msg:errMsg, err: e});
      }
    },

    /**
    * Respond to a ping control sent from a monitor
    *
    * @method ping_control
    * @param params {Object} Input parameters (not used)
    * @param callback {Function(error, response)} Called to send the message (or error) response.
    *

    *
error (Any) An object describing an error

    *
response (String) The string 'pong' is returned as the response

    *

    */
    ping_control: function(params, callback) {
      return callback(null, 'pong');
    }

  });

  // Register probe classes when loaded
  Probe.classes = {}; // key = name, data = class definition
  Probe.extend = function(params) {
    var t = this, probeClass = Backbone.Model.extend.apply(t, arguments);
    if (params.probeClass) {Probe.classes[params.probeClass] = probeClass;}
    return probeClass;
  };

  /**
  * Constructor for a list of Probe objects
  *
  *     var myList = new Probe.List(initialElements);
  *
  * @static
  * @method List
  * @param [items] {Array} Initial list items.  These can be raw JS objects or Probe data model objects.
  * @return {Backbone.Collection} Collection of Probe data model objects
  */
  Probe.List = Backbone.Collection.extend({model: Probe});

}(this));
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  template: require('./create-answer.html'),
  controller: ['$log', '$stateParams', '$rootScope', 'answerService', 'authService', CreateAnswerController],
  controllerAs: 'createAnswerCtrl',
};

function CreateAnswerController($log, $stateParams, $rootScope, answerService, authService) {
  $log.debug('CreateAnswerController');

  this.answer = {};

  this.createAnswer = function() {
    answerService.createAnswer($stateParams.id,this.answer)
    .then( () => {
      $rootScope.$broadcast('addAnswer', this.answer);
      this.answer.content = null;
      // this.answer.author = authService.currentUserId();
    });
  };
}
<commit_msg>answer routes fixed<commit_after>'use strict';

module.exports = {
  template: require('./create-answer.html'),
  controller: ['$log', '$stateParams', '$rootScope', 'answerService', 'authService', CreateAnswerController],
  controllerAs: 'createAnswerCtrl',
};

function CreateAnswerController($log, $stateParams, $rootScope, answerService, authService) {
  $log.debug('CreateAnswerController');

  this.answer = {};

  this.createAnswer = function() {
    answerService.createAnswer($stateParams.id,this.answer)
    .then( () => {
      $rootScope.$broadcast('addAnswer', this.answer);
      this.answer.content = null;
      // this.answer.author = authService.currentUserId();git s
    });
  };
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
/* globals jscolor */
frappe.provide("frappe.website_theme");
$.extend(frappe.website_theme, {
	color_variables: ["background_color", "top_bar_color", "top_bar_text_color",
		"footer_color", "footer_text_color", "text_color", "link_color"]
});

frappe.ui.form.on('Website Theme', {
	onload_post_render(frm) {
		frappe.require('assets/frappe/js/lib/jscolor/jscolor.js', function() {
			$.each(frappe.website_theme.color_variables, function(i, v) {
				$(frm.fields_dict[v].input).addClass('color {required:false,hash:true}');
			});
			jscolor.bind();
		});
	},
	refresh(frm) {
		frm.set_intro(__('Default theme is set in {0}', [''
			+ __('Website Settings') + '']));

		frm.toggle_display(["module", "custom"], !frappe.boot.developer_mode);

		if (!frm.doc.custom && !frappe.boot.developer_mode) {
			frm.set_read_only();
			frm.disable_save();
		} else {
			frm.enable_save();
		}
	}
})
<commit_msg>fix: Bootstrap default custom theme<commit_after>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
/* globals jscolor */
frappe.provide("frappe.website_theme");
$.extend(frappe.website_theme, {
	color_variables: ["background_color", "top_bar_color", "top_bar_text_color",
		"footer_color", "footer_text_color", "text_color", "link_color"]
});

frappe.ui.form.on('Website Theme', {
	onload_post_render(frm) {
		frappe.require('assets/frappe/js/lib/jscolor/jscolor.js', function() {
			$.each(frappe.website_theme.color_variables, function(i, v) {
				$(frm.fields_dict[v].input).addClass('color {required:false,hash:true}');
			});
			jscolor.bind();
		});
	},
	refresh(frm) {
		frm.set_intro(__('Default theme is set in {0}', [''
			+ __('Website Settings') + '']));

		frm.toggle_display(["module", "custom"], !frappe.boot.developer_mode);

		if (!frm.doc.custom && !frappe.boot.developer_mode) {
			frm.set_read_only();
			frm.disable_save();
		} else {
			frm.enable_save();
		}
	},
	apply_custom_theme(frm) {
		if (frm.doc.apply_custom_theme && !frm.doc.custom_theme) {
			frm.set_value('custom_theme', '$primary: #7575ff;\n\n@import "website";')
		}
	}
})
<|endoftext|>