<commit_before>/**
 * builds the 0th node, the content-node, in the create message graph
 *
 * Created by ksinger on 29.06.2015.
 */
//TODO switch to requirejs for dependency mngmt (so this lib isn't angular-bound)
//TODO replace calls to `won` object to `require('util')`
import won from "./won.js";
// import { useCases } from "useCaseDefinitions";
import { getAllDetails } from "../won-utils";

(function() {
  // <need-builder-js> scope

  function hasPriceSpecification() {
    return false; //TODO price-specification not fully implemented yet
  }
  function hasTimeConstraint() {
    return false; //TODO time-constraint-attachment not implemented yet
  }
  function hasAttachmentUrls(args) {
    return (
      args.attachmentUris &&
      Array.isArray(args.attachmentUris) &&
      args.attachmentUris.length > 0
    );
  }

  /**
   * Usage:  `won.buildNeedRdf(args)`
   * Where args consists of:
   *
   * **mandatory parameters:**
   *
   * * args.type: the type of the need (e.g. 'won:Supply')
   * * args.title: a string with the title (e.g. 'Couch to give away')
   * * args.description: a longer string describing the need in detail
   *
   * **optional parameters:**
   *    ```
   *    //comma-separated
   *    args.tags = 'Couch, furniture';
   *
   *    // this is the default
   *    args.facet = 'won:OwnerFacet';
   *    // the options here are:
   *    // * won.WON.OwnerFacetCompacted
   *    // * won.WON.GroupFacetCompacted
   *    // * won.WON.CoordinatorFacetCompacted
   *    // * won.WON.ParticipantFacetCompacted
   *    // * won.WON.CommentFacetCompacted
   *    // * 'won:CommentModeratedFacet'
   *    // * 'won:CommentUnrestrictedFacet'
   *    // * 'won:ControlFacet'
   *    // * 'won:BAPCCordinatorFacet'
   *    // * 'won:BAPCParticipantFacet'
   *    // * 'won:BACCCoordinatorFacet'
   *    // * 'won:BACCParticipantFacet'
   *    // * 'won:BAAtomicPCCoordinatorFacet'
   *    // * 'won:BAAtomicCCCoordinatorFacet'
   *
   *    args.latitude = 12.345678;
   *    args.longitude = 12.345678;
   *
   *    //no format assumed. this will just be attached as a string
   *    args.address = 'Yellowbrick Rd. 7, 12345 Oz';
   *
   *    // the URIs where attachments can be found / will be published
   *    args.attachmentUris = ['http://example.org/.../1234.png', 'http://example.org/.../1234.pdf']
   *
   *    // the triples will be put in the graph that's build here anyway, so there's no need to pass graph-uri
   *    args.arbitraryJsonLdGraph = [{ '@id': 'http://example.org/.../1234', 'dc:title': 'hi}, {...}, {...}]
   *
   *    args.recurInfinite =
   *    args.recursIn =
   *    args.startTime =
   *    args.endTime =
   *
   *    args.currency =
   *    args.lowerLimit =
   *    args.upperLimit =
   *    ```
   * @returns {{@id: string, @graph: {...}*}}
   *
   * NOTE: the function below makes heavy use of the fact that `undefined`
   * properties won't be included for stringification. This allows to
   * keep it readable (the alternative is a myriad of ternary statements or
   * splitting the graph-building in as many sub-functions)
   *
   *
   * //TODO mandatory but specify later:
   * contentId, e.g. 'http://localhost:8080/won/resource/event/1997814854983652400#content-need';
   */
  won.buildNeedRdf = function(args) {
    if (!args.is && !args.seeks) {
      throw new Error(
        "Expected an object with an is- and/or a seeks-subobject. Something like `{ is: {...}, seeks: {...} }`. Got " +
          JSON.stringify(args)
      );
    }

    /*
        const putIntoBoth =
            args.type === won.WON.BasicNeedTypeDotogetherCompacted;

        const putIntoIs =
            putIntoBoth ||
            args.type === won.WON.BasicNeedTypeSupplyCompacted;

        const putIntoSeeks =
            putIntoBoth ||
            args.type === won.WON.BasicNeedTypeDemandCompacted;

        let hasFlag = [];

        if(!!won.debugmode) {
            hasFlag.push("won:UsedForTesting");
        }

        if(!!args.whatsAround){
            hasFlag.push("won:WhatsAround");
            hasFlag.push("won:NoHintForCounterpart");
        }

        if(!!args.noHints){
            hasFlag.push("won:NoHintForMe");
            hasFlag.push("won:NoHintForCounterpart");
        }
        *

        //remove possible duplicates in hasFlag
        const result = [];
        hasFlag.forEach(function(item) {
            if(result.indexOf(item) < 0) {
                result.push(item);
            }
        });
        hasFlag = result;
        */

    const buildContentNode = (id, isOrSeeksData) => {
      let contentNode = {
        "@id": id,
        "dc:title": isOrSeeksData.title,
        "won:hasAttachment": hasAttachmentUrls(isOrSeeksData)
          ? isOrSeeksData.attachmentUris.map(uri => ({ "@id": uri }))
          : undefined,

        //TODO: Different id for is and seeks
        "won:hasTimeSpecification": !hasTimeConstraint(isOrSeeksData)
          ? undefined
          : {
              "@id": "_:timeSpecification",
              "@type": "won:TimeSpecification",
              "won:hasRecurInfiniteTimes": isOrSeeksData.recurInfinite,
              "won:hasRecursIn": isOrSeeksData.recursIn,
              "won:hasStartTime": isOrSeeksData.startTime,
              "won:hasEndTime": isOrSeeksData.endTime,
            },

        "won:hasPriceSpecificationhas": !hasPriceSpecification(isOrSeeksData)
          ? undefined
          : {
              "@id": "_:priceSpecification",
              "@type": "won:PriceSpecification",
              "won:hasCurrency": isOrSeeksData.currency,
              "won:hasLowerPriceLimit": isOrSeeksData.lowerPriceLimit,
              "won:hasUpperPriceLimit": isOrSeeksData.upperPriceLimit,
            },
        //TODO images, time, currency(?)
      };

      const detailList = getAllDetails();

      for (const detailName in detailList) {
        const detail = detailList[detailName];
        const detailRDF = {
          ...detail.parseToRDF({
            value: isOrSeeksData[detail.identifier],
            identifier: detail.identifier,
          }),
        };
        // add to content node
        for (const key in detailRDF) {
          contentNode[key] = detailRDF[key];
        }
      }
      return contentNode;
    };

    // TODO: if both is and seeks are present, the seeks content gets ignored here
    const isWhatsAround = args.is
      ? args.is.whatsAround
      : args.seeks.whatsAround;
    const isWhatsNew = args.is ? args.is.whatsNew : args.seeks.whatsNew;
    const noHints = args.is ? args.is.noHints : args.seeks.noHints;
    const matchingContext = args.matchingContext;
    const searchString = args.searchString;
    const noHintForCounterpart = isWhatsAround
      ? true
      : isWhatsNew
        ? true
        : args.searchString
          ? true
          : false;
    let isContentUri, seeksContentUri;
    if (isWhatsAround) {
      isContentUri = won.WON.contentNodeBlankUri.whatsAround;
      seeksContentUri = won.WON.contentNodeBlankUri.whatsAround;
    } else if (isWhatsNew) {
      isContentUri = won.WON.contentNodeBlankUri.whatsNew;
      seeksContentUri = won.WON.contentNodeBlankUri.whatsNew;
    } else {
      isContentUri = args.is ? won.WON.contentNodeBlankUri.is : undefined;
      seeksContentUri = args.seeks
        ? won.WON.contentNodeBlankUri.seeks
        : undefined;
    }
    const graph = [
      {
        "@id": args.is
          ? args.is.publishedContentUri
          : args.seeks.publishedContentUri,
        "@type": "won:Need",
        "won:is": isContentUri ? { "@id": isContentUri } : undefined,
        "won:seeks": seeksContentUri ? { "@id": seeksContentUri } : undefined,
        "won:hasFacet": args.facet ? args.facet : "won:OwnerFacet",
        "won:hasFlag": new Set([
          won.debugmode ? "won:UsedForTesting" : undefined,

          isWhatsAround ? "won:WhatsAround" : undefined,
          isWhatsNew ? "won:WhatsNew" : undefined,
          noHintForCounterpart ? "won:NoHintForCounterpart" : undefined,

          noHints ? "won:NoHintForMe" : undefined,
          noHints ? "won:NoHintForCounterpart" : undefined,
        ]), ///.toArray().filter(f => f),
        "won:hasMatchingContext": matchingContext ? matchingContext : undefined,
        "won:hasSearchString": searchString ? searchString : undefined,
      },
      //, <if _hasModalities> {... (see directly below) } </if>
      args.is ? buildContentNode(isContentUri, args.is) : {},
      args.seeks && !isWhatsAround
        ? buildContentNode(seeksContentUri, args.seeks)
        : {},
      ...(args.is && args.is.arbitraryJsonLd ? args.is.arbitraryJsonLd : []),
      ...(args.seeks && args.seeks.arbitraryJsonLd
        ? args.seeks.arbitraryJsonLd
        : []),
    ];
    return {
      "@graph": graph,
      "@context": {
        ...won.defaultContext, // needed for the arbitrary rdf

        //TODO probably an alias instead of an type declaration as it's intended here
        "won:hasCurrency": "xsd:string",
        "won:hasLowerPriceLimit": "xsd:float",
        "won:hasUpperPriceLimit": "xsd:float",

        //'geo:latitude': 'xsd:float',
        //'geo:longitude':'xsd:float',
        //'won:hasAddress': 'xsd:string',

        "won:hasStartTime": "xsd:dateTime",
        "won:hasEndTime": "xsd:dateTime",

        "won:hasFacet": {
          "@id": won.WON.hasFacet,
          "@type": "@id",
        },
        "won:hasFlag": {
          "@id": won.WON.hasFlag,
          "@type": "@id",
        },
      },
    };
  };
})(); // </need-builder-js>
<commit_msg>Allow searchstring in normal needs<commit_after>
/**
 * builds the 0th node, the content-node, in the create message graph
 *
 * Created by ksinger on 29.06.2015.
 */
//TODO switch to requirejs for dependency mngmt (so this lib isn't angular-bound)
//TODO replace calls to `won` object to `require('util')`
import won from "./won.js";
// import { useCases } from "useCaseDefinitions";
import { getAllDetails } from "../won-utils";

(function() {
  // <need-builder-js> scope

  function hasPriceSpecification() {
    return false; //TODO price-specification not fully implemented yet
  }
  function hasTimeConstraint() {
    return false; //TODO time-constraint-attachment not implemented yet
  }
  function hasAttachmentUrls(args) {
    return (
      args.attachmentUris &&
      Array.isArray(args.attachmentUris) &&
      args.attachmentUris.length > 0
    );
  }

  /**
   * Usage:  `won.buildNeedRdf(args)`
   * Where args consists of:
   *
   * **mandatory parameters:**
   *
   * * args.type: the type of the need (e.g. 'won:Supply')
   * * args.title: a string with the title (e.g. 'Couch to give away')
   * * args.description: a longer string describing the need in detail
   *
   * **optional parameters:**
   *    ```
   *    //comma-separated
   *    args.tags = 'Couch, furniture';
   *
   *    // this is the default
   *    args.facet = 'won:OwnerFacet';
   *    // the options here are:
   *    // * won.WON.OwnerFacetCompacted
   *    // * won.WON.GroupFacetCompacted
   *    // * won.WON.CoordinatorFacetCompacted
   *    // * won.WON.ParticipantFacetCompacted
   *    // * won.WON.CommentFacetCompacted
   *    // * 'won:CommentModeratedFacet'
   *    // * 'won:CommentUnrestrictedFacet'
   *    // * 'won:ControlFacet'
   *    // * 'won:BAPCCordinatorFacet'
   *    // * 'won:BAPCParticipantFacet'
   *    // * 'won:BACCCoordinatorFacet'
   *    // * 'won:BACCParticipantFacet'
   *    // * 'won:BAAtomicPCCoordinatorFacet'
   *    // * 'won:BAAtomicCCCoordinatorFacet'
   *
   *    args.latitude = 12.345678;
   *    args.longitude = 12.345678;
   *
   *    //no format assumed. this will just be attached as a string
   *    args.address = 'Yellowbrick Rd. 7, 12345 Oz';
   *
   *    // the URIs where attachments can be found / will be published
   *    args.attachmentUris = ['http://example.org/.../1234.png', 'http://example.org/.../1234.pdf']
   *
   *    // the triples will be put in the graph that's build here anyway, so there's no need to pass graph-uri
   *    args.arbitraryJsonLdGraph = [{ '@id': 'http://example.org/.../1234', 'dc:title': 'hi}, {...}, {...}]
   *
   *    args.recurInfinite =
   *    args.recursIn =
   *    args.startTime =
   *    args.endTime =
   *
   *    args.currency =
   *    args.lowerLimit =
   *    args.upperLimit =
   *    ```
   * @returns {{@id: string, @graph: {...}*}}
   *
   * NOTE: the function below makes heavy use of the fact that `undefined`
   * properties won't be included for stringification. This allows to
   * keep it readable (the alternative is a myriad of ternary statements or
   * splitting the graph-building in as many sub-functions)
   *
   *
   * //TODO mandatory but specify later:
   * contentId, e.g. 'http://localhost:8080/won/resource/event/1997814854983652400#content-need';
   */
  won.buildNeedRdf = function(args) {
    if (!args.is && !args.seeks) {
      throw new Error(
        "Expected an object with an is- and/or a seeks-subobject. Something like `{ is: {...}, seeks: {...} }`. Got " +
          JSON.stringify(args)
      );
    }

    /*
        const putIntoBoth =
            args.type === won.WON.BasicNeedTypeDotogetherCompacted;

        const putIntoIs =
            putIntoBoth ||
            args.type === won.WON.BasicNeedTypeSupplyCompacted;

        const putIntoSeeks =
            putIntoBoth ||
            args.type === won.WON.BasicNeedTypeDemandCompacted;

        let hasFlag = [];

        if(!!won.debugmode) {
            hasFlag.push("won:UsedForTesting");
        }

        if(!!args.whatsAround){
            hasFlag.push("won:WhatsAround");
            hasFlag.push("won:NoHintForCounterpart");
        }

        if(!!args.noHints){
            hasFlag.push("won:NoHintForMe");
            hasFlag.push("won:NoHintForCounterpart");
        }
        *

        //remove possible duplicates in hasFlag
        const result = [];
        hasFlag.forEach(function(item) {
            if(result.indexOf(item) < 0) {
                result.push(item);
            }
        });
        hasFlag = result;
        */

    const buildContentNode = (id, isOrSeeksData) => {
      let contentNode = {
        "@id": id,
        "dc:title": isOrSeeksData.title,
        "won:hasAttachment": hasAttachmentUrls(isOrSeeksData)
          ? isOrSeeksData.attachmentUris.map(uri => ({ "@id": uri }))
          : undefined,

        //TODO: Different id for is and seeks
        "won:hasTimeSpecification": !hasTimeConstraint(isOrSeeksData)
          ? undefined
          : {
              "@id": "_:timeSpecification",
              "@type": "won:TimeSpecification",
              "won:hasRecurInfiniteTimes": isOrSeeksData.recurInfinite,
              "won:hasRecursIn": isOrSeeksData.recursIn,
              "won:hasStartTime": isOrSeeksData.startTime,
              "won:hasEndTime": isOrSeeksData.endTime,
            },

        "won:hasPriceSpecificationhas": !hasPriceSpecification(isOrSeeksData)
          ? undefined
          : {
              "@id": "_:priceSpecification",
              "@type": "won:PriceSpecification",
              "won:hasCurrency": isOrSeeksData.currency,
              "won:hasLowerPriceLimit": isOrSeeksData.lowerPriceLimit,
              "won:hasUpperPriceLimit": isOrSeeksData.upperPriceLimit,
            },
        //TODO images, time, currency(?)
      };

      const detailList = getAllDetails();

      for (const detailName in detailList) {
        const detail = detailList[detailName];
        const detailRDF = {
          ...detail.parseToRDF({
            value: isOrSeeksData[detail.identifier],
            identifier: detail.identifier,
          }),
        };
        // add to content node
        for (const key in detailRDF) {
          contentNode[key] = detailRDF[key];
        }
      }
      return contentNode;
    };

    // TODO: if both is and seeks are present, the seeks content gets ignored here
    const isWhatsAround = args.is
      ? args.is.whatsAround
      : args.seeks.whatsAround;
    const isWhatsNew = args.is ? args.is.whatsNew : args.seeks.whatsNew;
    const noHints = args.is ? args.is.noHints : args.seeks.noHints;
    const matchingContext = args.matchingContext;
    const searchString = args.searchString;
    const noHintForCounterpart = isWhatsAround
      ? true
      : isWhatsNew
        ? true
        : args.searchString && args.useCase === 'pureSearch' //hack: no hint for counterpart only if it's a pure search
          ? true
          : false;
    let isContentUri, seeksContentUri;
    if (isWhatsAround) {
      isContentUri = won.WON.contentNodeBlankUri.whatsAround;
      seeksContentUri = won.WON.contentNodeBlankUri.whatsAround;
    } else if (isWhatsNew) {
      isContentUri = won.WON.contentNodeBlankUri.whatsNew;
      seeksContentUri = won.WON.contentNodeBlankUri.whatsNew;
    } else {
      isContentUri = args.is ? won.WON.contentNodeBlankUri.is : undefined;
      seeksContentUri = args.seeks
        ? won.WON.contentNodeBlankUri.seeks
        : undefined;
    }
    const graph = [
      {
        "@id": args.is
          ? args.is.publishedContentUri
          : args.seeks.publishedContentUri,
        "@type": "won:Need",
        "won:is": isContentUri ? { "@id": isContentUri } : undefined,
        "won:seeks": seeksContentUri ? { "@id": seeksContentUri } : undefined,
        "won:hasFacet": args.facet ? args.facet : "won:OwnerFacet",
        "won:hasFlag": new Set([
          won.debugmode ? "won:UsedForTesting" : undefined,

          isWhatsAround ? "won:WhatsAround" : undefined,
          isWhatsNew ? "won:WhatsNew" : undefined,
          noHintForCounterpart ? "won:NoHintForCounterpart" : undefined,

          noHints ? "won:NoHintForMe" : undefined,
          noHints ? "won:NoHintForCounterpart" : undefined,
        ]), ///.toArray().filter(f => f),
        "won:hasMatchingContext": matchingContext ? matchingContext : undefined,
        "won:hasSearchString": searchString ? searchString : undefined,
      },
      //, <if _hasModalities> {... (see directly below) } </if>
      args.is ? buildContentNode(isContentUri, args.is) : {},
      args.seeks && !isWhatsAround
        ? buildContentNode(seeksContentUri, args.seeks)
        : {},
      ...(args.is && args.is.arbitraryJsonLd ? args.is.arbitraryJsonLd : []),
      ...(args.seeks && args.seeks.arbitraryJsonLd
        ? args.seeks.arbitraryJsonLd
        : []),
    ];
    return {
      "@graph": graph,
      "@context": {
        ...won.defaultContext, // needed for the arbitrary rdf

        //TODO probably an alias instead of an type declaration as it's intended here
        "won:hasCurrency": "xsd:string",
        "won:hasLowerPriceLimit": "xsd:float",
        "won:hasUpperPriceLimit": "xsd:float",

        //'geo:latitude': 'xsd:float',
        //'geo:longitude':'xsd:float',
        //'won:hasAddress': 'xsd:string',

        "won:hasStartTime": "xsd:dateTime",
        "won:hasEndTime": "xsd:dateTime",

        "won:hasFacet": {
          "@id": won.WON.hasFacet,
          "@type": "@id",
        },
        "won:hasFlag": {
          "@id": won.WON.hasFlag,
          "@type": "@id",
        },
      },
    };
  };
})(); // </need-builder-js>
<|endoftext|>


<commit_before>// @api private
const
  noop = () => {},
  notImplemented = (param, done = noop) => {
    done(new Error('not implemented'));
  };

class Provider {
  constructor() {
    this.id = 'unknown';
    this.name = '알수없음';
    this.source = 'unknown';
    this.TRACKING_REGEXP = /^.+$/;
  }

  validate(tracking, done = noop) {
    const str = typeof tracking === 'number' ? `${tracking}` : tracking;

    try {
      done(null, !!str.match(this.TRACKING_REGEXP));
    } catch (e) {
      done(e);
    }
  }

  fetch(...args) {
    notImplemented.apply(this, args);
  }

  handleResponse(e, res, body, done) {
    if (e) { return done(e); }

    if (res.statusCode !== 200) {
      return done(new Error('response status isnt 200'));
    }

    done(null, body);
  }

  parse(...args) {
    notImplemented.apply(this, args);
  }

  execute(tracking, done = noop) {
    this.validate(tracking, (e, isValid) => {
      if (e) { return done(e); }
      if (!isValid) { return done(new Error('invalid tracking')); }

      this.fetch(tracking, (e, body) => {
        if (e) { return done(e); }

        this.parse(body, (e, result) => {
          if (e) { return done(e); }

          done(null, result);
        });
      });
    });
  }

  static noop() { }
}

module.exports = exports = Provider;
<commit_msg>Provider: Added `validateMagicNumber` static method<commit_after>// @api private
const
  noop = () => {},
  notImplemented = (param, done = noop) => {
    done(new Error('not implemented'));
  };

class Provider {
  constructor() {
    this.id = 'unknown';
    this.name = '알수없음';
    this.source = 'unknown';
    this.TRACKING_REGEXP = /^.+$/;
  }

  validate(tracking, done = noop) {
    const str = typeof tracking === 'number' ? `${tracking}` : tracking;

    try {
      done(null, !!str.match(this.TRACKING_REGEXP));
    } catch (e) {
      done(e);
    }
  }

  fetch(...args) {
    notImplemented.apply(this, args);
  }

  handleResponse(e, res, body, done) {
    if (e) { return done(e); }

    if (res.statusCode !== 200) {
      return done(new Error('response status isnt 200'));
    }

    done(null, body);
  }

  parse(...args) {
    notImplemented.apply(this, args);
  }

  execute(tracking, done = noop) {
    this.validate(tracking, (e, isValid) => {
      if (e) { return done(e); }
      if (!isValid) { return done(new Error('invalid tracking')); }

      this.fetch(tracking, (e, body) => {
        if (e) { return done(e); }

        this.parse(body, (e, result) => {
          if (e) { return done(e); }

          done(null, result);
        });
      });
    });
  }

  static noop() { }

  static validateMagicNumber(tracking) {
    const str = typeof tracking !== 'string' ? `${tracking}` : tracking;
    let
      payload = null,
      magic = null;

    if (str.length < 2) { return false; }

    payload = +str.substr(0, str.length - 1);
    magic = +str.substr(str.length - 1);

    return (payload % 7) === magic;
  }
}

module.exports = exports = Provider;
<|endoftext|>


<commit_before>module.exports = function (kuzzle) {
  var
    _ = require('lodash'),
    q = require('q'),
    extend = require('util')._extend,
    uuid = require('node-uuid'),
    User = require('../security/user')(kuzzle),
    Repository = require('./repository'),
    InternalError = require('kuzzle-common-objects').Errors.internalError;

  function UserRepository (opts) {
    var options = opts || {};

    if (options.ttl !== undefined) {
      this.ttl = options.ttl;
    }
  }

  UserRepository.prototype = new Repository(kuzzle, {
    index: kuzzle.config.internalIndex,
    collection: 'users',
    ObjectConstructor: User,
    cacheEngine: kuzzle.services.list.userCache
  });

  UserRepository.prototype.load = function (id) {
    if (id === 'anonymous' || id === -1) {
      return this.anonymous();
    }

    return Repository.prototype.load.call(this, id);
  };

  UserRepository.prototype.persist = function (user, opts) {
    var
      options = opts || {},
      databaseOptions = options.database || {},
      cacheOptions = options.cache || {};

    if (user._id === undefined || user._id === null) {
      user._id = uuid.v4();
    }

    return this.persistToDatabase(user, databaseOptions)
      .then(() => this.persistToCache(user, cacheOptions))
      .then(() => q(user));
  };

  UserRepository.prototype.anonymous = function () {
    var
      user = new User();

    return this.hydrate(user, {
      _id: -1,
      name: 'Anonymous',
      profile: 'anonymous'
    });
  };

  UserRepository.prototype.hydrate = function (user, data) {
    var
      result,
      source;

    if (!_.isObject(data)) {
      return q(user);
    }

    return Repository.prototype.hydrate(user, data)
      .then(u => {
        result = u;

        if (!result.profile && result._source) {
          source = result._source;
          delete result._source;
          extend(result, source);
        }

        console.log(result);

        if (result._id === undefined || result._id === null) {
          return this.anonymous()
            .then(anonymousUser => {
              result = anonymousUser;
              return anonymousUser.profile;
            });
        }

        // if the user exists (have an _id) but no profile
        // set it to default
        if (!result.profile) {
          return kuzzle.repositories.profile.loadProfile('default');
        }

        return kuzzle.repositories.profile.loadProfile(result.profile);
      })
      .then((profile) => {
        if (!profile) {
          return q.reject(new InternalError('Could not find profile: ' + user.profile));
        }
        result.profile = profile;
        return result;
      });
  };

  UserRepository.prototype.serializeToCache = function (user) {
    var result = {};

    Object.keys(user).forEach(function (key) {
      if (key !== 'profile') {
        result[key] = user[key];
      }
    });
    result.profile = user.profile._id;

    return result;
  };

  UserRepository.prototype.serializeToDatabase = function (user) {
    var result = this.serializeToCache(user);

    delete result._id;

    return result;
  };

  return UserRepository;

};

<commit_msg>remove console log<commit_after>module.exports = function (kuzzle) {
  var
    _ = require('lodash'),
    q = require('q'),
    extend = require('util')._extend,
    uuid = require('node-uuid'),
    User = require('../security/user')(kuzzle),
    Repository = require('./repository'),
    InternalError = require('kuzzle-common-objects').Errors.internalError;

  function UserRepository (opts) {
    var options = opts || {};

    if (options.ttl !== undefined) {
      this.ttl = options.ttl;
    }
  }

  UserRepository.prototype = new Repository(kuzzle, {
    index: kuzzle.config.internalIndex,
    collection: 'users',
    ObjectConstructor: User,
    cacheEngine: kuzzle.services.list.userCache
  });

  UserRepository.prototype.load = function (id) {
    if (id === 'anonymous' || id === -1) {
      return this.anonymous();
    }

    return Repository.prototype.load.call(this, id);
  };

  UserRepository.prototype.persist = function (user, opts) {
    var
      options = opts || {},
      databaseOptions = options.database || {},
      cacheOptions = options.cache || {};

    if (user._id === undefined || user._id === null) {
      user._id = uuid.v4();
    }

    return this.persistToDatabase(user, databaseOptions)
      .then(() => this.persistToCache(user, cacheOptions))
      .then(() => q(user));
  };

  UserRepository.prototype.anonymous = function () {
    var
      user = new User();

    return this.hydrate(user, {
      _id: -1,
      name: 'Anonymous',
      profile: 'anonymous'
    });
  };

  UserRepository.prototype.hydrate = function (user, data) {
    var
      result,
      source;

    if (!_.isObject(data)) {
      return q(user);
    }

    return Repository.prototype.hydrate(user, data)
      .then(u => {
        result = u;

        if (!result.profile && result._source) {
          source = result._source;
          delete result._source;
          extend(result, source);
        }

        if (result._id === undefined || result._id === null) {
          return this.anonymous()
            .then(anonymousUser => {
              result = anonymousUser;
              return anonymousUser.profile;
            });
        }

        // if the user exists (have an _id) but no profile
        // set it to default
        if (!result.profile) {
          return kuzzle.repositories.profile.loadProfile('default');
        }

        return kuzzle.repositories.profile.loadProfile(result.profile);
      })
      .then((profile) => {
        if (!profile) {
          return q.reject(new InternalError('Could not find profile: ' + user.profile));
        }
        result.profile = profile;
        return result;
      });
  };

  UserRepository.prototype.serializeToCache = function (user) {
    var result = {};

    Object.keys(user).forEach(function (key) {
      if (key !== 'profile') {
        result[key] = user[key];
      }
    });
    result.profile = user.profile._id;

    return result;
  };

  UserRepository.prototype.serializeToDatabase = function (user) {
    var result = this.serializeToCache(user);

    delete result._id;

    return result;
  };

  return UserRepository;

};

<|endoftext|>


<commit_before>import ariatiseForm from '../../utils/ariatiseForm';
import { Tinymce } from '../../utils/tinymce';

$(() => {
  ariatiseForm({ selector: '#new_edit_guidance' });
  Tinymce.init({ selector: '#guidance-text' });
});
<commit_msg>updated tinymce selector for guidance (#1645)<commit_after>import ariatiseForm from '../../utils/ariatiseForm';
import { Tinymce } from '../../utils/tinymce';

$(() => {
  Tinymce.init({ selector: '#guidance-text' });
  ariatiseForm({ selector: '#new_edit_guidance' });
});
<|endoftext|>


<commit_before>describe('mapview', function () {

  var view, layerView, master_vis;

  beforeEach(function () {
    var table = TestUtil.createTable('test');
    var vis = TestUtil.createVis('jam');
    master_vis = TestUtil.createVis('jam');
    var map = new cdb.admin.Map();
    var layer = new cdb.admin.CartoDBLayer({
      table_name: 'test',
      tile_style: 'test',
      user_name: 'test',
      attribution: 'attribution1'
    });
    map.layers.add(layer);
    map.layers.add(new cdb.admin.CartoDBLayer({
      table_name: 'test2',
      tile_style: 'style',
      user_name: 'test',
      attribution: 'attribution2'
    }));
    var element = $('

');
    element.appendTo($('body'));

    view = new cdb.admin.MapTab({
      user: TestUtil.createUser('jamon'),
      model: map,
      vis: vis,
      master_vis: master_vis,
      menu: new cdb.admin.RightMenu({}),
      geocoder: new cdb.admin.Geocoding('', table),
      el: element,
      baseLayers: new cdb.admin.Layers([ new cdb.admin.TileLayer({ urlTemplate: 'rabos'}) ])
    });

    view.enableMap();

    layerView = new cdb.admin.LayerPanelView({
      model: layer,
      vis: TestUtil.createVis(),
      user: TestUtil.createUser('jamon'),
      globalError: new cdb.admin.GlobalError({ el: $('
') })
    });
    view.setActiveLayer(layerView);
  });

  afterEach(function () {
    if (view.options.geocoder.dlg) view.options.geocoder.dlg.hide();
    if (view.noGeoRefDialog) view.noGeoRefDialog.clean();
    if (view.pecanDialog) view.pecanDialog.clean();
    localStorage.clear();
    view.$el.html('').remove();
    $('.dropdown').remove();
  });

  it('should render the map container', function () {
    view.render();
    expect(view.$('.cartodb-map').length).toEqual(1);
  });

  it('should render the basemap_dropdown', function () {
    view.render();
    expect(view.$('.basemap_dropdown').length).toEqual(1);
  });

  xit('should trigger the georef warning when none of the rows contain geom info', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], []);
    view.table._data.reset([
      {'the_geom': '', 'name': 'Benidorm'},
      {'the_geom': '', 'name': 'San Juan'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog).toBeTruthy();
  });

  it('should trigger the georef warning only once when there is no geom in the table', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], []);
    view.table._data.reset([
      {'the_geom': '', 'name': 'Benidorm'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    view.noGeoRefDialog.clean();
    view.noGeoRefDialog = undefined;
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(true);
  });

  it('should trigger the georef warning when there is no geom in the table and there was a table with the same name in the past', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], [], '12345');
    view.table._data.reset([
      {'the_geom': '', 'name': 'Benidorm'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(false);

    // Clean that view to reuse it
    view.noGeoRefDialog.clean();
    view.noGeoRefDialog = undefined;

    // New table with the same name (test)
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry']], [], '45678');
    view.table._data.reset([
      {'the_geom': ''}
    ]);
    view.bindGeoRefCheck();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(false);
  });

  it('should NOT trigger the georef warning when there is no data in the table', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry']], []);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(true);
  });

  it('should NOT trigger the georef warning when there is some data with geom info', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], []);
    view.table._data.reset([
      {'the_geom': '{"type":"Point","coordinates":["1","1"]}', 'name': 'Benidorm'},
      {'the_geom': '', 'name': 'San Juan'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    // toBeFalsy failes due a infinite loop in jasmine formatter
    expect(view.noGeoRefDialog === undefined).toEqual(true);
  });

  it('should trigger the no-geo warning when there is data without geom info and it is in read-only mode', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], [], '12345');
    spyOn(view.table, 'isSync').and.returnValue(true);
    spyOn(view.table, 'data').and.returnValue(['hello']);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(true);
    expect(view.noGeoWarningDialog === undefined).toEqual(false);
  });

  it('should have a geocoding binding each time map view is rendered', function () {
    view.render();
    spyOn(view.layerModel.table, 'fetch');
    view.options.geocoder.trigger('geocodingComplete');
    expect(view.layerModel.table.fetch).not.toHaveBeenCalled();
    view.clearMap();
    view.render();
    view.options.geocoder.trigger('geocodingComplete');
    expect(view.layerModel.table.fetch).not.toHaveBeenCalled();
    // It has to be 0, no more calls for table fetch, tableTab does it now
    expect(view.layerModel.table.fetch.calls.count()).toBe(0);
  });

  it('should bind new geometry event in the current layer view', function () {
    spyOn(view.geometryEditor, 'createGeom');
    layerView.model.trigger('startEdition', 'point');
    expect(view.geometryEditor.createGeom).toHaveBeenCalled();
  });

  it('should bind new geometry event in the current layer view', function () {
    spyOn(view.geometryEditor, 'createGeom');
    layerView.model.trigger('startEdition', 'point');
    expect(view.geometryEditor.createGeom).toHaveBeenCalled();
  });

  it('should switch map type when master vis change type', function () {
    master_vis.set('type', 'table');
    spyOn(view, 'switchMapType');
    master_vis.set('type', 'derived');
    expect(view.switchMapType).toHaveBeenCalled();
  });

  it('should render attributions of each layer and default CARTO attribution', function () {
    var attributions = view.$el.find('.leaflet-control-attribution').html();
    expect(attributions).toEqual('attribution1, attribution2, © CARTO');
  });

  describe('cdb.admin.MapTab.updateDataLayerView', function () {
    describe('given MapTab view has a cdb.CartoDB.Layer as data layer view', function () {
      beforeEach(function () {
        spyOn(view.layerDataView, 'invalidate');
        view.updateDataLayerView();
      });

      it('should invalidate the data layer view (e.g. to reload tiles)', function () {
        expect(view.layerDataView.invalidate).toHaveBeenCalled();
      });
    });
  });
});
<commit_msg>Frozen random failures.<commit_after>describe('mapview', function () {

  var view, layerView, master_vis;

  beforeEach(function () {
    var table = TestUtil.createTable('test');
    var vis = TestUtil.createVis('jam');
    master_vis = TestUtil.createVis('jam');
    var map = new cdb.admin.Map();
    var layer = new cdb.admin.CartoDBLayer({
      table_name: 'test',
      tile_style: 'test',
      user_name: 'test',
      attribution: 'attribution1'
    });
    map.layers.add(layer);
    map.layers.add(new cdb.admin.CartoDBLayer({
      table_name: 'test2',
      tile_style: 'style',
      user_name: 'test',
      attribution: 'attribution2'
    }));
    var element = $('

');
    element.appendTo($('body'));

    view = new cdb.admin.MapTab({
      user: TestUtil.createUser('jamon'),
      model: map,
      vis: vis,
      master_vis: master_vis,
      menu: new cdb.admin.RightMenu({}),
      geocoder: new cdb.admin.Geocoding('', table),
      el: element,
      baseLayers: new cdb.admin.Layers([ new cdb.admin.TileLayer({ urlTemplate: 'rabos'}) ])
    });

    view.enableMap();

    layerView = new cdb.admin.LayerPanelView({
      model: layer,
      vis: TestUtil.createVis(),
      user: TestUtil.createUser('jamon'),
      globalError: new cdb.admin.GlobalError({ el: $('
') })
    });
    view.setActiveLayer(layerView);
  });

  afterEach(function () {
    if (view.options.geocoder.dlg) view.options.geocoder.dlg.hide();
    if (view.noGeoRefDialog) view.noGeoRefDialog.clean();
    if (view.pecanDialog) view.pecanDialog.clean();
    localStorage.clear();
    view.remove();
    $('.dropdown').remove();
  });

  it('should render the map container', function () {
    view.render();
    expect(view.$('.cartodb-map').length).toEqual(1);
  });

  it('should render the basemap_dropdown', function () {
    view.render();
    expect(view.$('.basemap_dropdown').length).toEqual(1);
  });

  xit('should trigger the georef warning when none of the rows contain geom info', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], []);
    view.table._data.reset([
      {'the_geom': '', 'name': 'Benidorm'},
      {'the_geom': '', 'name': 'San Juan'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog).toBeTruthy();
  });

  xit('should trigger the georef warning only once when there is no geom in the table', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], []);
    view.table._data.reset([
      {'the_geom': '', 'name': 'Benidorm'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    view.noGeoRefDialog.clean();
    view.noGeoRefDialog = undefined;
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(true);
  });

  xit('should trigger the georef warning when there is no geom in the table and there was a table with the same name in the past', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], [], '12345');
    view.table._data.reset([
      {'the_geom': '', 'name': 'Benidorm'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(false);

    // Clean that view to reuse it
    view.noGeoRefDialog.clean();
    view.noGeoRefDialog = undefined;

    // New table with the same name (test)
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry']], [], '45678');
    view.table._data.reset([
      {'the_geom': ''}
    ]);
    view.bindGeoRefCheck();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(false);
  });

  it('should NOT trigger the georef warning when there is no data in the table', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry']], []);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(true);
  });

  it('should NOT trigger the georef warning when there is some data with geom info', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], []);
    view.table._data.reset([
      {'the_geom': '{"type":"Point","coordinates":["1","1"]}', 'name': 'Benidorm'},
      {'the_geom': '', 'name': 'San Juan'}
    ]);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    // toBeFalsy failes due a infinite loop in jasmine formatter
    expect(view.noGeoRefDialog === undefined).toEqual(true);
  });

  it('should trigger the no-geo warning when there is data without geom info and it is in read-only mode', function () {
    view.table = TestUtil.createTable('test', [['the_geom', 'geometry'], ['name', 'string']], [], '12345');
    spyOn(view.table, 'isSync').and.returnValue(true);
    spyOn(view.table, 'data').and.returnValue(['hello']);
    view.bindGeoRefCheck();
    view.render();
    view.table.trigger('dataLoaded');
    expect(view.noGeoRefDialog === undefined).toEqual(true);
    expect(view.noGeoWarningDialog === undefined).toEqual(false);
  });

  it('should have a geocoding binding each time map view is rendered', function () {
    view.render();
    spyOn(view.layerModel.table, 'fetch');
    view.options.geocoder.trigger('geocodingComplete');
    expect(view.layerModel.table.fetch).not.toHaveBeenCalled();
    view.clearMap();
    view.render();
    view.options.geocoder.trigger('geocodingComplete');
    expect(view.layerModel.table.fetch).not.toHaveBeenCalled();
    // It has to be 0, no more calls for table fetch, tableTab does it now
    expect(view.layerModel.table.fetch.calls.count()).toBe(0);
  });

  it('should bind new geometry event in the current layer view', function () {
    spyOn(view.geometryEditor, 'createGeom');
    layerView.model.trigger('startEdition', 'point');
    expect(view.geometryEditor.createGeom).toHaveBeenCalled();
  });

  it('should bind new geometry event in the current layer view', function () {
    spyOn(view.geometryEditor, 'createGeom');
    layerView.model.trigger('startEdition', 'point');
    expect(view.geometryEditor.createGeom).toHaveBeenCalled();
  });

  it('should switch map type when master vis change type', function () {
    master_vis.set('type', 'table');
    spyOn(view, 'switchMapType');
    master_vis.set('type', 'derived');
    expect(view.switchMapType).toHaveBeenCalled();
  });

  it('should render attributions of each layer and default CARTO attribution', function () {
    var attributions = view.$el.find('.leaflet-control-attribution').html();
    expect(attributions).toEqual('attribution1, attribution2, © CARTO');
  });

  describe('cdb.admin.MapTab.updateDataLayerView', function () {
    describe('given MapTab view has a cdb.CartoDB.Layer as data layer view', function () {
      beforeEach(function () {
        spyOn(view.layerDataView, 'invalidate');
        view.updateDataLayerView();
      });

      it('should invalidate the data layer view (e.g. to reload tiles)', function () {
        expect(view.layerDataView.invalidate).toHaveBeenCalled();
      });
    });
  });
});
<|endoftext|>


<commit_before>'use strict';
module.exports = `
const observer = new PerformanceObserver(list => {});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
const entries = observer.takeRecords();
if (entries.length > 0) {
    const largestEntry = entries[entries.length - 1];
    const clientRect = largestEntry.element.getBoundingClientRect();

    const canvas = document.createElement('canvas'); //Create a canvas element
    canvas.style.width='100%';
    canvas.style.height='100%';
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.position='absolute';
    canvas.style.left=0;
    canvas.style.top=0;
    canvas.style.zIndex=2147483646;
    canvas.id = "browsertime-lcp";
    document.body.appendChild(canvas);
    const context = canvas.getContext('2d');
    context.rect(Math.max(0,clientRect.x), Math.max(0,clientRect.y), Math.min(clientRect.width, window.innerWidth - clientRect.x) , Math.min(clientRect.height, window.innerHeight-clientRect.y));
    context.lineWidth = "6";
    context.strokeStyle = "red";
    context.stroke();
}
`;
<commit_msg>Add some alpha fill on LCP (#1564)<commit_after>'use strict';
module.exports = `
const observer = new PerformanceObserver(list => {});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
const entries = observer.takeRecords();
if (entries.length > 0) {
    const largestEntry = entries[entries.length - 1];
    const clientRect = largestEntry.element.getBoundingClientRect();

    const canvas = document.createElement('canvas'); //Create a canvas element
    canvas.style.width='100%';
    canvas.style.height='100%';
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.position='absolute';
    canvas.style.left=0;
    canvas.style.top=0;
    canvas.style.zIndex=2147483646;
    canvas.id = "browsertime-lcp";
    document.body.appendChild(canvas);
    const context = canvas.getContext('2d');
    context.rect(Math.max(0,clientRect.x), Math.max(0,clientRect.y), Math.min(clientRect.width, window.innerWidth - clientRect.x) , Math.min(clientRect.height, window.innerHeight-clientRect.y));
    context.lineWidth = "6";
    context.strokeStyle = "red";
    context.stroke();

    context.fillStyle = "red";
    context.globalAlpha = 0.1;
    context.rect(Math.max(0,clientRect.x), Math.max(0,clientRect.y), Math.min(clientRect.width, window.innerWidth - clientRect.x) , Math.min(clientRect.height, window.innerHeight-clientRect.y));
    context.fill();
}
`;
<|endoftext|>


<commit_before>class MCProcessesGraphComponentController {
    /*@ngInject*/
    constructor() {
        this.cy = null;
    }

    $onInit() {
        let transformingProcesses = this.processes.filter(p => p.does_transform);
        let sample2InputProcess = {};
        let sample2OutputProcess = {};
        transformingProcesses.forEach(p => {
            p.input_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                sample2InputProcess[id] = p;
            });

            p.output_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                sample2OutputProcess[id] = p;
            })
        });
        let elements = this.processes.map(p => {
            console.log(p.name, p);
            return {
                data: {
                    id: p.id,
                    name: p.name,
                    color: p.does_transform ? 'red' : '#999999'
                }
            }
        });
        this.processes.filter(p => !p.does_transform).forEach(p => {
            p.input_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                let process = sample2OutputProcess[id];
                if (process) {
                    elements.push({
                        data: {
                            id: `${p.id}_${process.id}`,
                            source: process.id,
                            target: p.id
                        }
                    });
                }
                process = sample2InputProcess[id];
                if (process) {
                    elements.push({
                        data: {
                            source: p.id,
                            target: process.id
                        }
                    });
                }
            });
        });

        let sampleName2Sample = {};
        this.processes.forEach(p => {
            p.input_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
            p.output_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
        });
        this.samples = _.values(sampleName2Sample);
        this.cy = cytoscape({
            container: document.getElementById('processesGraph'),
            elements: elements,
            style: [
                {
                    selector: 'node',
                    style: {
                        'label': 'data(name)',
                        'background-color': 'data(color)'
                    }
                },
                {
                    selector: 'edge',
                    style: {
                        'width': 4,
                        'target-arrow-shape': 'triangle',
                        //'target-arrow-color': '#9dbaea',
                        'curve-style': 'bezier'
                    }
                }
            ]
        });
        this.cy.on('click', function(event) {
            console.log('node or edge clicked', event);
            let target = event.cyTarget;
            console.log('node name is', target.data('name'));
        });
        cy.layout({name: 'dagre'});
    }

    filterOnSample(sample) {
        console.log('filterOnSample', sample);
        let matches = this.cy.nodes().filter(`[name = '${sample.name}']`);
        console.log(sample);
    }
}

angular.module('materialscommons').component('mcProcessesGraph', {
    templateUrl: 'app/global.components/graph/mc-processes-graph.html',
    controller: MCProcessesGraphComponentController,
    bindings: {
        processes: '<'
    }
});
<commit_msg>Refer to this.cy, rather than cy.<commit_after>class MCProcessesGraphComponentController {
    /*@ngInject*/
    constructor() {
        this.cy = null;
    }

    $onInit() {
        let transformingProcesses = this.processes.filter(p => p.does_transform);
        let sample2InputProcess = {};
        let sample2OutputProcess = {};
        transformingProcesses.forEach(p => {
            p.input_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                sample2InputProcess[id] = p;
            });

            p.output_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                sample2OutputProcess[id] = p;
            })
        });
        let elements = this.processes.map(p => {
            console.log(p.name, p);
            return {
                data: {
                    id: p.id,
                    name: p.name,
                    color: p.does_transform ? 'red' : '#999999'
                }
            }
        });
        this.processes.filter(p => !p.does_transform).forEach(p => {
            p.input_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                let process = sample2OutputProcess[id];
                if (process) {
                    elements.push({
                        data: {
                            id: `${p.id}_${process.id}`,
                            source: process.id,
                            target: p.id
                        }
                    });
                }
                process = sample2InputProcess[id];
                if (process) {
                    elements.push({
                        data: {
                            source: p.id,
                            target: process.id
                        }
                    });
                }
            });
        });

        let sampleName2Sample = {};
        this.processes.forEach(p => {
            p.input_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
            p.output_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
        });
        this.samples = _.values(sampleName2Sample);
        this.cy = cytoscape({
            container: document.getElementById('processesGraph'),
            elements: elements,
            style: [
                {
                    selector: 'node',
                    style: {
                        'label': 'data(name)',
                        'background-color': 'data(color)'
                    }
                },
                {
                    selector: 'edge',
                    style: {
                        'width': 4,
                        'target-arrow-shape': 'triangle',
                        //'target-arrow-color': '#9dbaea',
                        'curve-style': 'bezier'
                    }
                }
            ]
        });
        this.cy.on('click', function(event) {
            console.log('node or edge clicked', event);
            let target = event.cyTarget;
            console.log('node name is', target.data('name'));
        });
        this.cy.layout({name: 'dagre'});
    }

    filterOnSample(sample) {
        console.log('filterOnSample', sample);
        let matches = this.cy.nodes().filter(`[name = '${sample.name}']`);
        console.log(sample);
    }
}

angular.module('materialscommons').component('mcProcessesGraph', {
    templateUrl: 'app/global.components/graph/mc-processes-graph.html',
    controller: MCProcessesGraphComponentController,
    bindings: {
        processes: '<'
    }
});
<|endoftext|>


<commit_before>import {
    replaceWithHeaderSection,
    replaceWithListSection
} from 'mobiledoc-kit/editor/text-input-handlers';

// Text expansions watch text entry events and will look for matches, replacing
// the matches with additional markup, atoms, or cards
// https://github.com/bustlelabs/mobiledoc-kit#responding-to-text-input

// TODO: this was copied from our old Koenig editor, it could do with some
// comments, cleanup, and refactoring

export default function (editor) {
    // We don't want to run all our content rules on every text entry event,
    // instead we check to see if this text entry event could match a content
    // rule, and only then run the rules. Right now we only want to match
    // content ending with *, _, ), ~, and `. This could increase as we support
    // more markdown.

    editor.onTextInput({
        name: 'inline_markdown',
        match: /[*_)~`]$/,
        run(editor, matches) {
            let text = editor.range.head.section.textUntil(editor.range.head);
            let hasTextAfter = editor.range.head.section.text.length > text.length;

            switch (matches[0]) {
            case '*':
                matchStrongStar(editor, text, hasTextAfter);
                matchEmStar(editor, text, hasTextAfter);
                break;
            case '_':
                matchStrongUnderscore(editor, text, hasTextAfter);
                matchEmUnderscore(editor, text, hasTextAfter);
                break;
            case ')':
                matchLink(editor, text, hasTextAfter);
                matchImage(editor, text, hasTextAfter);
                break;
            case '~':
                matchStrikethrough(editor, text, hasTextAfter);
                break;
            case '`':
                matchCode(editor, text, hasTextAfter);
                break;
            }
        }
    });

    /* block level markdown ------------------------------------------------- */

    // mobiledoc-kit has `* ` already built-in so we only need to add `- `
    editor.onTextInput({
        name: 'md_ul',
        match: /^- $/,
        run(editor) {
            replaceWithListSection(editor, 'ul');
        }
    });

    editor.onTextInput({
        name: 'md_blockquote',
        match: /^> $/,
        run(editor) {
            replaceWithHeaderSection(editor, 'blockquote');
        }
    });

    editor.onTextInput({
        name: 'md_hr',
        match: /^---$/,
        run(editor) {
            let {range: {head, head: {section}}} = editor;

            // Skip if cursor is not at end of section
            if (!head.isTail()) {
                return;
            }

            // Skip if section is a list item
            if (section.isListItem) {
                return;
            }

            editor.run((postEditor) => {
                let card = postEditor.builder.createCardSection('hr');
                let needsTrailingParagraph = !section.next;

                postEditor.replaceSection(section, card);

                // add an empty paragraph after if necessary so writing can continue
                if (needsTrailingParagraph) {
                    let newSection = postEditor.builder.createMarkupSection('p');
                    postEditor.insertSectionAtEnd(newSection);
                    postEditor.setRange(newSection.tailPosition());
                }
            });
        }
    });

    /* inline markdown ------------------------------------------------------ */

    function matchStrongStar(editor, text, hasTextAfter = false) {
        let {range} = editor;
        let matches = text.match(/(^|\s)\*\*([^\s*].+?[^\s*])\*\*/);
        if (matches) {
            let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));
            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let bold = postEditor.builder.createMarkup('strong');
                let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [bold]);
                if (!hasTextAfter) {
                    postEditor.insertTextWithMarkup(nextPosition, ' ', []);
                }
            });
        }
    }

    function matchStrongUnderscore(editor, text, hasTextAfter = false) {
        let {range} = editor;
        let matches = text.match(/(^|\s)__([^\s_].+?[^\s_])__/);
        if (matches) {
            let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));
            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let bold = postEditor.builder.createMarkup('strong');
                let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [bold]);
                if (!hasTextAfter) {
                    postEditor.insertTextWithMarkup(nextPosition, ' ', []);
                }
            });
        }
    }

    function matchEmStar(editor, text, hasTextAfter = false) {
        let {range} = editor;
        let matches = text.match(/(^|\s)\*([^\s*][^*]+?[^\s])\*/);
        if (matches) {
            let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));
            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let em = postEditor.builder.createMarkup('em');
                let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [em]);
                if (!hasTextAfter) {
                    postEditor.insertTextWithMarkup(nextPosition, ' ', []);
                }
            });
        }
    }

    function matchEmUnderscore(editor, text, hasTextAfter = false) {
        let {range} = editor;
        let matches = text.match(/(^|\s)_([^\s_][^_]+?[^\s])_/);
        if (matches) {
            let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));
            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let em = postEditor.builder.createMarkup('em');
                let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [em]);
                if (!hasTextAfter) {
                    postEditor.insertTextWithMarkup(nextPosition, ' ', []);
                }
            });
        }
    }

    function matchStrikethrough(editor, text, hasTextAfter = false) {
        let {range} = editor;
        let matches = text.match(/(^|\s)~([^\s~][^~]+?[^\s])~/);
        if (matches) {
            let match = matches[0][0] === '~' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));
            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let s = postEditor.builder.createMarkup('s');
                let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [s]);
                if (!hasTextAfter) {
                    postEditor.insertTextWithMarkup(nextPosition, ' ', []); // insert the un-marked-up space
                }
            });
        }
    }

    function matchCode(editor, text, hasTextAfter = false) {
        let {range} = editor;
        let matches = text.match(/(^|\s)`([^\s`][^`]+?[^\s])`/);
        if (matches) {
            let match = matches[0][0] === '`' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));
            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let code = postEditor.builder.createMarkup('code');
                let nextPosition = postEditor.insertTextWithMarkup(position, matches[2], [code]);
                if (!hasTextAfter) {
                    postEditor.insertTextWithMarkup(nextPosition, ' ', []); // insert the un-marked-up space
                }
            });
        }
    }

    function matchLink(editor, text, hasTextAfter = false) {
        let {range} = editor;
        let matches = text.match(/(^|[^!])\[(.*?)\]\((.*?)\)$/);
        if (matches) {
            let url = matches[3];
            let text = matches[2];
            let match = matches[0][0] === '[' ? matches[0] : matches[0].substr(1);
            range = range.extend(-match.length);
            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let a = postEditor.builder.createMarkup('a', {href: url});
                let nextPosition = postEditor.insertTextWithMarkup(position, text, [a]);
                if (!hasTextAfter) {
                    postEditor.insertTextWithMarkup(nextPosition, ' ', []); // insert the un-marked-up space
                }
            });
        }
    }

    function matchImage(editor, text) {
        let matches = text.match(/^!\[(.*?)\]\((.*?)\)$/);
        if (matches) {
            let {range: {head, head: {section}}} = editor;
            let src = matches[2];
            let alt = matches[1];

            // skip if cursor is not at end of section
            if (!head.isTail()) {
                return;
            }

            // mobiledoc lists don't support cards
            if (section.isListItem) {
                return;
            }

            editor.run((postEditor) => {
                let card = postEditor.builder.createCardSection('image', {src, alt});
                // need to check the section before replacing else it will always
                // add a trailing paragraph
                let needsTrailingParagraph = !section.next;

                editor.range.extend(-(matches[0].length));
                postEditor.replaceSection(editor.range.headSection, card);

                if (needsTrailingParagraph) {
                    let newSection = editor.builder.createMarkupSection('p');
                    postEditor.insertSectionAtEnd(newSection);
                    postEditor.setRange(newSection.tailPosition());
                }
            });
        }
    }
}
<commit_msg>Koenig - Fixed trailing-spaces when using markdown text expansions<commit_after>import {
    replaceWithHeaderSection,
    replaceWithListSection
} from 'mobiledoc-kit/editor/text-input-handlers';
import {run} from '@ember/runloop';

// Text expansions watch text entry events and will look for matches, replacing
// the matches with additional markup, atoms, or cards
// https://github.com/bustlelabs/mobiledoc-kit#responding-to-text-input

// TODO: this was copied from our old Koenig editor, it could do with some
// comments, cleanup, and refactoring

export default function (editor) {
    // We don't want to run all our content rules on every text entry event,
    // instead we check to see if this text entry event could match a content
    // rule, and only then run the rules. Right now we only want to match
    // content ending with *, _, ), ~, and `. This could increase as we support
    // more markdown.

    editor.onTextInput({
        name: 'inline_markdown',
        match: /[*_)~`]$/,
        run(editor, matches) {
            let text = editor.range.head.section.textUntil(editor.range.head);

            switch (matches[0]) {
            case '*':
                matchStrongStar(editor, text);
                matchEmStar(editor, text);
                break;
            case '_':
                matchStrongUnderscore(editor, text);
                matchEmUnderscore(editor, text);
                break;
            case ')':
                matchLink(editor, text);
                matchImage(editor, text);
                break;
            case '~':
                matchStrikethrough(editor, text);
                break;
            case '`':
                matchCode(editor, text);
                break;
            }
        }
    });

    /* block level markdown ------------------------------------------------- */

    // mobiledoc-kit has `* ` already built-in so we only need to add `- `
    editor.onTextInput({
        name: 'md_ul',
        match: /^- $/,
        run(editor) {
            replaceWithListSection(editor, 'ul');
        }
    });

    editor.onTextInput({
        name: 'md_blockquote',
        match: /^> $/,
        run(editor) {
            replaceWithHeaderSection(editor, 'blockquote');
        }
    });

    editor.onTextInput({
        name: 'md_hr',
        match: /^---$/,
        run(editor) {
            let {range: {head, head: {section}}} = editor;

            // Skip if cursor is not at end of section
            if (!head.isTail()) {
                return;
            }

            // Skip if section is a list item
            if (section.isListItem) {
                return;
            }

            editor.run((postEditor) => {
                let card = postEditor.builder.createCardSection('hr');
                let needsTrailingParagraph = !section.next;

                postEditor.replaceSection(section, card);

                // add an empty paragraph after if necessary so writing can continue
                if (needsTrailingParagraph) {
                    let newSection = postEditor.builder.createMarkupSection('p');
                    postEditor.insertSectionAtEnd(newSection);
                    postEditor.setRange(newSection.tailPosition());
                }
            });
        }
    });

    /* inline markdown ------------------------------------------------------ */

    function matchStrongStar(editor, text) {
        let {range} = editor;
        let matches = text.match(/(^|\s)\*\*([^\s*].+?[^\s*])\*\*/);
        if (matches) {
            let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));

            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let bold = postEditor.builder.createMarkup('strong');
                postEditor.insertTextWithMarkup(position, matches[2], [bold]);
            });
        }

        // must be scheduled so that the toggle isn't reset automatically
        run.schedule('actions', this, function () {
            editor.toggleMarkup('strong');
        });
    }

    function matchStrongUnderscore(editor, text) {
        let {range} = editor;
        let matches = text.match(/(^|\s)__([^\s_].+?[^\s_])__/);
        if (matches) {
            let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));

            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let bold = postEditor.builder.createMarkup('strong');
                postEditor.insertTextWithMarkup(position, matches[2], [bold]);
            });

            // must be scheduled so that the toggle isn't reset automatically
            run.schedule('actions', this, function () {
                editor.toggleMarkup('strong');
            });
        }
    }

    function matchEmStar(editor, text) {
        let {range} = editor;
        let matches = text.match(/(^|\s)\*([^\s*][^*]+?[^\s])\*/);
        if (matches) {
            let match = matches[0][0] === '*' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));

            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let em = postEditor.builder.createMarkup('em');
                postEditor.insertTextWithMarkup(position, matches[2], [em]);
            });

            // must be scheduled so that the toggle isn't reset automatically
            run.schedule('actions', this, function () {
                editor.toggleMarkup('em');
            });
        }
    }

    function matchEmUnderscore(editor, text) {
        let {range} = editor;
        let matches = text.match(/(^|\s)_([^\s_][^_]+?[^\s])_/);
        if (matches) {
            let match = matches[0][0] === '_' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));

            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let em = postEditor.builder.createMarkup('em');
                postEditor.insertTextWithMarkup(position, matches[2], [em]);
            });

            // must be scheduled so that the toggle isn't reset automatically
            run.schedule('actions', this, function () {
                editor.toggleMarkup('code');
            });
        }
    }

    function matchStrikethrough(editor, text) {
        let {range} = editor;
        let matches = text.match(/(^|\s)~([^\s~][^~]+?[^\s])~/);
        if (matches) {
            let match = matches[0][0] === '~' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));

            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let s = postEditor.builder.createMarkup('s');
                postEditor.insertTextWithMarkup(position, matches[2], [s]);
            });

            // must be scheduled so that the toggle isn't reset automatically
            run.schedule('actions', this, function () {
                editor.toggleMarkup('s');
            });
        }
    }

    function matchCode(editor, text) {
        let {range} = editor;
        let matches = text.match(/(^|\s)`([^\s`][^`]+?[^\s])`/);
        if (matches) {
            let match = matches[0][0] === '`' ? matches[0] : matches[0].substr(1);
            range = range.extend(-(match.length));

            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let code = postEditor.builder.createMarkup('code');
                postEditor.insertTextWithMarkup(position, matches[2], [code]);
            });

            // must be scheduled so that the toggle isn't reset automatically
            run.schedule('actions', this, function () {
                editor.toggleMarkup('code');
            });
        }
    }

    function matchLink(editor, text) {
        let {range} = editor;
        let matches = text.match(/(^|[^!])\[(.*?)\]\((.*?)\)$/);
        if (matches) {
            let url = matches[3];
            let text = matches[2];
            let match = matches[0][0] === '[' ? matches[0] : matches[0].substr(1);
            range = range.extend(-match.length);

            editor.run((postEditor) => {
                let position = postEditor.deleteRange(range);
                let a = postEditor.builder.createMarkup('a', {href: url});
                postEditor.insertTextWithMarkup(position, text, [a]);
            });

            // must be scheduled so that the toggle isn't reset automatically
            run.schedule('actions', this, function () {
                editor.toggleMarkup('code');
            });
        }
    }

    function matchImage(editor, text) {
        let matches = text.match(/^!\[(.*?)\]\((.*?)\)$/);
        if (matches) {
            let {range: {head, head: {section}}} = editor;
            let src = matches[2];
            let alt = matches[1];

            // skip if cursor is not at end of section
            if (!head.isTail()) {
                return;
            }

            // mobiledoc lists don't support cards
            if (section.isListItem) {
                return;
            }

            editor.run((postEditor) => {
                let card = postEditor.builder.createCardSection('image', {src, alt});
                // need to check the section before replacing else it will always
                // add a trailing paragraph
                let needsTrailingParagraph = !section.next;

                editor.range.extend(-(matches[0].length));
                postEditor.replaceSection(editor.range.headSection, card);

                if (needsTrailingParagraph) {
                    let newSection = editor.builder.createMarkupSection('p');
                    postEditor.insertSectionAtEnd(newSection);
                    postEditor.setRange(newSection.tailPosition());
                }
            });
        }
    }
}
<|endoftext|>


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

'use strict';

// MODULES //

var tape = require( 'tape' );
var Complex128 = require( '@stdlib/complex/float64' );
var Complex64 = require( '@stdlib/complex/float32' );
var conj = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof conj, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function returns the complex conjugate of a complex number', function test( t ) {
	var v;
	var z;

	z = new Complex128( 3.14, -3.14 );
	v = conj( z );
	t.strictEqual( v.re, 3.14, 'returns expected value' );
	t.strictEqual( v.im, 3.14, 'returns expected value' );

	z = new Complex64( 3.14, -3.14 );
	v = conj( z );
	t.strictEqual( v.re, 3.140000104904175, 'returns expected value' );
	t.strictEqual( v.im, 3.140000104904175, 'returns expected value' );

	t.end();
});
<commit_msg>Remove test<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var Complex128 = require( '@stdlib/complex/float64' );
var conj = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof conj, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function returns the complex conjugate of a complex number', function test( t ) {
	var v;
	var z;

	z = new Complex128( 3.14, -3.14 );
	v = conj( z );
	t.strictEqual( v.re, 3.14, 'returns expected value' );
	t.strictEqual( v.im, 3.14, 'returns expected value' );

	t.end();
});
<|endoftext|>


<commit_before>module.exports = {
  init: require("./init"),
  compile: require("./compile"),
  migrate: require("./migrate"),
  deploy: require("./deploy"),
  build: require("./build"),
  test: require("./test"),
  debug: require("./debug"),
  opcode: require("./opcode"),
  console: require("./console"),
  develop: require("./develop"),
  create: require("./create"),
  help: require("./help"),
  install: require("./install"),
  publish: require("./publish"),
  networks: require("./networks"),
  watch: require("./watch"),
  exec: require("./exec"),
  unbox: require("./unbox"),
  version: require("./version"),
};
<commit_msg>Order index file alphabetically so the help displays them in that order<commit_after>module.exports = {
  build: require("./build"),
  compile: require("./compile"),
  console: require("./console"),
  create: require("./create"),
  debug: require("./debug"),
  deploy: require("./deploy"),
  develop: require("./develop"),
  exec: require("./exec"),
  help: require("./help"),
  init: require("./init"),
  install: require("./install"),
  migrate: require("./migrate"),
  networks: require("./networks"),
  opcode: require("./opcode"),
  publish: require("./publish"),
  test: require("./test"),
  unbox: require("./unbox"),
  version: require("./version"),
  watch: require("./watch"),
};
<|endoftext|>


<commit_before>import {hasCornerRadius, rectangle} from '../path/shapes';
import boundStroke from '../bound/boundStroke';
import {intersectRect} from '../util/intersect';
import value from '../util/value';
import {pickVisit, visit} from '../util/visit';
import blend from '../util/canvas/blend';
import {clipGroup} from '../util/canvas/clip';
import fill from '../util/canvas/fill';
import stroke from '../util/canvas/stroke';
import {hitPath} from '../util/canvas/pick';
import clip from '../util/svg/clip';
import {translateItem} from '../util/svg/transform';

function offset(item) {
  const sw = value(item.strokeWidth, 1);
  return item.strokeOffset != null ? item.strokeOffset
    : item.stroke && sw > 0.5 && sw < 1.5 ? 0.5 - Math.abs(sw - 1)
    : 0;
}

function attr(emit, item) {
  emit('transform', translateItem(item));
}

function emitRectangle(emit, item) {
  const off = offset(item);
  emit('d', rectangle(null, item, off, off));
}

function background(emit, item) {
  emit('class', 'background');
  emit('aria-hidden', true);
  emitRectangle(emit, item);
}

function foreground(emit, item) {
  emit('class', 'foreground');
  emit('aria-hidden', true);
  if (item.strokeForeground) {
    emitRectangle(emit, item);
  } else {
    emit('d', '');
  }
}

function content(emit, item, renderer) {
  const url = item.clip ? clip(renderer, item, item) : null;
  emit('clip-path', url);
}

function bound(bounds, group) {
  if (!group.clip && group.items) {
    const items = group.items, m = items.length;
    for (let j=0; j<m; ++j) {
      bounds.union(items[j].bounds);
    }
  }

  if ((group.clip || group.width || group.height) && !group.noBound) {
    bounds.add(0, 0).add(group.width || 0, group.height || 0);
  }

  boundStroke(bounds, group);

  return bounds.translate(group.x || 0, group.y || 0);
}

function rectanglePath(context, group, x, y) {
  const off = offset(group);
  context.beginPath();
  rectangle(context, group, (x || 0) + off, (y || 0) + off);
}

const hitBackground = hitPath(rectanglePath);
const hitForeground = hitPath(rectanglePath, false);

function draw(context, scene, bounds) {
  visit(scene, group => {
    const gx = group.x || 0,
          gy = group.y || 0,
          fore = group.strokeForeground,
          opacity = group.opacity == null ? 1 : group.opacity;

    // draw group background
    if ((group.stroke || group.fill) && opacity) {
      rectanglePath(context, group, gx, gy);
      blend(context, group);
      if (group.fill && fill(context, group, opacity)) {
        context.fill();
      }
      if (group.stroke && !fore && stroke(context, group, opacity)) {
        context.stroke();
      }
    }

    // setup graphics context, set clip and bounds
    context.save();
    context.translate(gx, gy);
    if (group.clip) clipGroup(context, group);
    if (bounds) bounds.translate(-gx, -gy);

    // draw group contents
    visit(group, item => {
      this.draw(context, item, bounds);
    });

    // restore graphics context
    if (bounds) bounds.translate(gx, gy);
    context.restore();

    // draw group foreground
    if (fore && group.stroke && opacity) {
      rectanglePath(context, group, gx, gy);
      blend(context, group);
      if (stroke(context, group, opacity)) {
        context.stroke();
      }
    }
  });
}

function pick(context, scene, x, y, gx, gy) {
  if (scene.bounds && !scene.bounds.contains(gx, gy) || !scene.items) {
    return null;
  }

  const cx = x * context.pixelRatio,
        cy = y * context.pixelRatio;

  return pickVisit(scene, group => {
    let hit, fore, ix, dx, dy, dw, dh, b, c;

    // first hit test bounding box
    b = group.bounds;
    if (b && !b.contains(gx, gy)) return;

    // passed bounds check, test rectangular clip
    dx = group.x || 0;
    dy = group.y || 0;
    dw = dx + (group.width || 0);
    dh = dy + (group.height || 0);
    c = group.clip;
    if (c && (gx < dx || gx > dw || gy < dy || gy > dh)) return;

    // adjust coordinate system
    context.save();
    context.translate(dx, dy);
    dx = gx - dx;
    dy = gy - dy;

    // test background for rounded corner clip
    if (c && hasCornerRadius(group) && !hitBackground(context, group, cx, cy)) {
      context.restore();
      return null;
    }

    fore = group.strokeForeground;
    ix = scene.interactive !== false;

    // hit test against group foreground
    if (ix && fore && group.stroke
        && hitForeground(context, group, cx, cy)) {
      context.restore();
      return group;
    }

    // hit test against contained marks
    hit = pickVisit(group, mark => pickMark(mark, dx, dy)
      ? this.pick(mark, x, y, dx, dy)
      : null
    );

    // hit test against group background
    if (!hit && ix && (group.fill || (!fore && group.stroke))
        && hitBackground(context, group, cx, cy)) {
      hit = group;
    }

    // restore state and return
    context.restore();
    return hit || null;
  });
}

function pickMark(mark, x, y) {
  return (mark.interactive !== false || mark.marktype === 'group')
    && mark.bounds && mark.bounds.contains(x, y);
}

export default {
  type:       'group',
  tag:        'g',
  nested:     false,
  attr:       attr,
  bound:      bound,
  draw:       draw,
  pick:       pick,
  isect:      intersectRect,
  content:    content,
  background: background,
  foreground: foreground
};
<commit_msg>Fix group picking with clip and corner radius. (#2797)<commit_after>import {hasCornerRadius, rectangle} from '../path/shapes';
import boundStroke from '../bound/boundStroke';
import {intersectRect} from '../util/intersect';
import value from '../util/value';
import {pickVisit, visit} from '../util/visit';
import blend from '../util/canvas/blend';
import {clipGroup} from '../util/canvas/clip';
import fill from '../util/canvas/fill';
import stroke from '../util/canvas/stroke';
import {hitPath} from '../util/canvas/pick';
import clip from '../util/svg/clip';
import {translateItem} from '../util/svg/transform';

function offset(item) {
  const sw = value(item.strokeWidth, 1);
  return item.strokeOffset != null ? item.strokeOffset
    : item.stroke && sw > 0.5 && sw < 1.5 ? 0.5 - Math.abs(sw - 1)
    : 0;
}

function attr(emit, item) {
  emit('transform', translateItem(item));
}

function emitRectangle(emit, item) {
  const off = offset(item);
  emit('d', rectangle(null, item, off, off));
}

function background(emit, item) {
  emit('class', 'background');
  emit('aria-hidden', true);
  emitRectangle(emit, item);
}

function foreground(emit, item) {
  emit('class', 'foreground');
  emit('aria-hidden', true);
  if (item.strokeForeground) {
    emitRectangle(emit, item);
  } else {
    emit('d', '');
  }
}

function content(emit, item, renderer) {
  const url = item.clip ? clip(renderer, item, item) : null;
  emit('clip-path', url);
}

function bound(bounds, group) {
  if (!group.clip && group.items) {
    const items = group.items, m = items.length;
    for (let j=0; j<m; ++j) {
      bounds.union(items[j].bounds);
    }
  }

  if ((group.clip || group.width || group.height) && !group.noBound) {
    bounds.add(0, 0).add(group.width || 0, group.height || 0);
  }

  boundStroke(bounds, group);

  return bounds.translate(group.x || 0, group.y || 0);
}

function rectanglePath(context, group, x, y) {
  const off = offset(group);
  context.beginPath();
  rectangle(context, group, (x || 0) + off, (y || 0) + off);
}

const hitBackground = hitPath(rectanglePath);
const hitForeground = hitPath(rectanglePath, false);
const hitCorner = hitPath(rectanglePath, true);

function draw(context, scene, bounds) {
  visit(scene, group => {
    const gx = group.x || 0,
          gy = group.y || 0,
          fore = group.strokeForeground,
          opacity = group.opacity == null ? 1 : group.opacity;

    // draw group background
    if ((group.stroke || group.fill) && opacity) {
      rectanglePath(context, group, gx, gy);
      blend(context, group);
      if (group.fill && fill(context, group, opacity)) {
        context.fill();
      }
      if (group.stroke && !fore && stroke(context, group, opacity)) {
        context.stroke();
      }
    }

    // setup graphics context, set clip and bounds
    context.save();
    context.translate(gx, gy);
    if (group.clip) clipGroup(context, group);
    if (bounds) bounds.translate(-gx, -gy);

    // draw group contents
    visit(group, item => {
      this.draw(context, item, bounds);
    });

    // restore graphics context
    if (bounds) bounds.translate(gx, gy);
    context.restore();

    // draw group foreground
    if (fore && group.stroke && opacity) {
      rectanglePath(context, group, gx, gy);
      blend(context, group);
      if (stroke(context, group, opacity)) {
        context.stroke();
      }
    }
  });
}

function pick(context, scene, x, y, gx, gy) {
  if (scene.bounds && !scene.bounds.contains(gx, gy) || !scene.items) {
    return null;
  }

  const cx = x * context.pixelRatio,
        cy = y * context.pixelRatio;

  return pickVisit(scene, group => {
    let hit, fore, ix, dx, dy, dw, dh, b, c;

    // first hit test bounding box
    b = group.bounds;
    if (b && !b.contains(gx, gy)) return;

    // passed bounds check, test rectangular clip
    dx = group.x || 0;
    dy = group.y || 0;
    dw = dx + (group.width || 0);
    dh = dy + (group.height || 0);
    c = group.clip;
    if (c && (gx < dx || gx > dw || gy < dy || gy > dh)) return;

    // adjust coordinate system
    context.save();
    context.translate(dx, dy);
    dx = gx - dx;
    dy = gy - dy;

    // test background for rounded corner clip
    if (c && hasCornerRadius(group) && !hitCorner(context, group, cx, cy)) {
      context.restore();
      return null;
    }

    fore = group.strokeForeground;
    ix = scene.interactive !== false;

    // hit test against group foreground
    if (ix && fore && group.stroke
        && hitForeground(context, group, cx, cy)) {
      context.restore();
      return group;
    }

    // hit test against contained marks
    hit = pickVisit(group, mark => pickMark(mark, dx, dy)
      ? this.pick(mark, x, y, dx, dy)
      : null
    );

    // hit test against group background
    if (!hit && ix && (group.fill || (!fore && group.stroke))
        && hitBackground(context, group, cx, cy)) {
      hit = group;
    }

    // restore state and return
    context.restore();
    return hit || null;
  });
}

function pickMark(mark, x, y) {
  return (mark.interactive !== false || mark.marktype === 'group')
    && mark.bounds && mark.bounds.contains(x, y);
}

export default {
  type:       'group',
  tag:        'g',
  nested:     false,
  attr:       attr,
  bound:      bound,
  draw:       draw,
  pick:       pick,
  isect:      intersectRect,
  content:    content,
  background: background,
  foreground: foreground
};
<|endoftext|>


<commit_before>var definition = {
    frame: {
        header: [ 16, {
            fin: 1, rsv1: 1, rsv2: 1, rsv3: 1, opcode: 4,
            mask: 1, length: 7
        } ],
        length: [ function (object) {
            switch (object.header.length) {
                case 127:
                    return 0
                case 126:
                    return 1
                default:
                    object.length = object.header.length
            }
        }, 16, 32 ],
        mask: [ function (object) {
            return object.mask ? 1 : 0
        }, 0, 16 ]
    },
    mysql: {
        value: [ 8, function (value) {
            if (value < 0xfb) {
                return 0
            } else if (value & 0xfc) {
                return 1
            }
        }, 'b8', [ 'x8', 'b16' ] ]
    }
}

var packets = {
    frame: function (object, parsing) {
        if (!parsing) {
            header.mask = object.mask == null ? 0 : 1
        }
        _(object.header, {
            fin: 1, rsv1: 1, rsv2: 2, rsv3: 3, opcode: 4,
            mask: 1, length: 7
        })
        if (header.length == 127) {
            _(header.length, 16)
        } else if (header.length == 126) {
            _(header.length, 32)
        } else if (parsing) {
            object.length = header.length
        }
        if (header.mask) {
            _(object.mask, 16)
        }
    },
    mysql: function (object) {
        if (parsing) {
            _(object.value, 8)
            if (object.value & 0x0fc) {
                _(object.value, 16)
            } else if (object.value & 0xfd) {
                _(object.value, 24)
            } else if (object.value & 0xfe) {
                _(object.value, 64)
            }
        } else {
            if (object.value < 251) {
                _(object.value, 8)
            } else if (object.value > 251 && object.value < 0xffff) {
                _(0xfc)
                _(object.value, 16)
            } else if (object.value >= 0xffff && object.value < 0xffffff) {
                _(0xfd)
                _(object.value, 24)
            } else {
                _(0xfe)
                _(object.value, 64)
            }
        }
    },
    nested: function (object) {
        _(object.numbers, 16, [32])
        _(object.structures, 16, [function (struct) {
            _(struct.count, packets.mysql)
            _(struct.string, [8], [0])
        }])
    }
}

packets.lengthEncoded = function (_, object) {
    _(object.array, 16, [function () {
        _('name', 'b16')
    }])
}

packets.websocket = function (_, object) {
    _('header', function (_) {
        _({ fin: 1, rsv1: 1, rsv2: 1, rsv3: 1, opcode: 4, mask: 1, length: 7 })
    })
    var header = object.header
    if (header.length == 127) {
        _('length', 16)
    } else if (header.length == 126) {
        _('length', 32)
    } else if (parsing) {
        object.length = header.length
    }
    if (header.mask == 1) {
        _(object.mask, 16)
    }
}

var packets = {
    frame: function (object) {
        if (serializing) {
            header.mask = object.mask == null ? 0 : 1
        }
        header = packed(object.header, 16, {
            fin: 1, rsv1: 1, rsv2: 2, rsv3: 3, opcode: 4,
            mask: 1, length: 7
        })
        switch (header.length) {
        case 127:
            unsigned(header.length, 16)
        case 126:
            unsigned(header.length, 32)
        default:
            if (parsing) {
                object.length = header.length
            }
        }
        if (header.mask) {
            unsigned(object.mask, 16)
        }
    },
    mysql: function (object) {
        object.value = get(8)
        if (object.value & 0xfc) {
            object.value = get(16)
        }
    },
    nested: function (object) {
    }
}
<commit_msg>Thoughts on read-ahead.<commit_after>var definition = {
    frame: {
        header: [ 16, {
            fin: 1, rsv1: 1, rsv2: 1, rsv3: 1, opcode: 4,
            mask: 1, length: 7
        } ],
        length: [ function (object) {
            switch (object.header.length) {
                case 127:
                    return 0
                case 126:
                    return 1
                default:
                    object.length = object.header.length
            }
        }, 16, 32 ],
        mask: [ function (object) {
            return object.mask ? 1 : 0
        }, 0, 16 ]
    },
    mysql: {
        value: [ 8, function (value) {
            if (value < 0xfb) {
                return 0
            } else if (value & 0xfc) {
                return 1
            }
        }, 'b8', [ 'x8', 'b16' ] ]
    }
}

var packets = {
    frame: function (object, parsing) {
        if (!parsing) {
            header.mask = object.mask == null ? 0 : 1
        }
        _(object.header, {
            fin: 1, rsv1: 1, rsv2: 2, rsv3: 3, opcode: 4,
            mask: 1, length: 7
        })
        if (header.length == 127) {
            _(header.length, 16)
        } else if (header.length == 126) {
            _(header.length, 32)
        } else if (parsing) {
            object.length = header.length
        }
        if (header.mask) {
            _(object.mask, 16)
        }
    },
    mysql: function (object) {
        if (parsing) {
            _(object.value, 8)
            if (object.value & 0x0fc) {
                _(object.value, 16)
            } else if (object.value & 0xfd) {
                _(object.value, 24)
            } else if (object.value & 0xfe) {
                _(object.value, 64)
            }
        } else {
            if (object.value < 251) {
                _(object.value, 8)
            } else if (object.value > 251 && object.value < 0xffff) {
                _(0xfc)
                _(object.value, 16)
            } else if (object.value >= 0xffff && object.value < 0xffffff) {
                _(0xfd)
                _(object.value, 24)
            } else {
                _(0xfe)
                _(object.value, 64)
            }
        }
    },
    nested: function (object) {
        _(object.numbers, 16, [32])
        _(object.structures, 16, [function (struct) {
            _(struct.count, packets.mysql)
            _(struct.string, [8], [0])
        }])
    }
}

packets.lengthEncoded = function (_, object) {
    _(object.array, 16, [function () {
        _('name', 'b16')
    }])
}

var packet = function () {}

packets.websocket = packet(function (packet, object) {
    if (parsing) {
        var peek = packet({ flag: 3, $padding: 5 }, 'flag')
        if (peek & ~0x7f == 0) {
            packet('id', { $flag: 1, value: 7 }, 'value')
        } else {
            packet('id', { $flag: 2, value: 14 }, 'value')
        }
    } else {
        if (object.id < 0x7f) {
            packet('id', 8, 0x80 & object.id)
        } else if (object.id < 65500) {
            packet('id', 16, 0xb000 & object.id)
        } else if (object.id < 222) {
        }
    }
    packet('.', {
        fin: 1, rsv1: 1, rsv2: 1, rsv3: 1, opcode: 4, masked: 1, length: 7
    })
    if (object.length == 127) {
        packet('length', 16)
    } else if (object.length == 126) {
        packet('length', 32)
    }
    if (object.masked == 1) {
        packet(object.mask, 16)
    }
})

var packets = {
    frame: function (object) {
        if (serializing) {
            header.mask = object.mask == null ? 0 : 1
        }
        header = packed(object.header, 16, {
            fin: 1, rsv1: 1, rsv2: 2, rsv3: 3, opcode: 4,
            mask: 1, length: 7
        })
        switch (header.length) {
        case 127:
            unsigned(header.length, 16)
        case 126:
            unsigned(header.length, 32)
        default:
            if (parsing) {
                object.length = header.length
            }
        }
        if (header.mask) {
            unsigned(object.mask, 16)
        }
    },
    mysql: function (object) {
        object.value = get(8)
        if (object.value & 0xfc) {
            object.value = get(16)
        }
    },
    nested: function (object) {
    }
}
<|endoftext|>