<commit_before>;(function (undefined) {
    'use strict';

    if (typeof sigma === 'undefined') {
    	throw 'sigma is not declared';
    }

    if (!('Promise' in window)) {
    	throw 'Your browser must support Promise Object';
    }

    var driver = null,
        sig = null,
        version = null;

    // Declare neo4j package
    sigma.utils.pkg("sigma.neo4j");

    /*
     * Convert the Record object of neo4j bolt web driver in order to get
     * the integer value
     *
     * @param {Record} primitive.   The Record object returned by neo4j bolt web api.
     *
     */
    var convertPrimitive = function convertPrimitive (primitive) {
        var keys = Object.keys(primitive.properties);
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i],
                property = primitive.properties[key];
            if (typeof property === 'object'
                    && 'high' in property && 'low' in property) {
                property = property.low;
            }
        }
        primitive.identity = primitive.identity.low;
        if ('start' in primitive && 'end' in primitive) {
            primitive.start = primitive.start.low;
            primitive.end = primitive.end.low;
        }
    };

    /**
     * This function parse a neo4j cypher query result, and transform it into
     * a sigma graph object. (Inspired by sigma.neo4j.cypher plugin)
     *
     * @param {Result} response.   The Result object returned by neo4j bolt web api.
     *
     * @return {graph} Sigma.js Graph object
     */
    var driverResultToSigmaGraph = function driverResultToSigmaGraph (response) {
        var graph = { nodes: [], edges: [] },
            nodesMap = {},
            edgesMap = {},
            key;

        response.records.forEach(function (record) {
            record._fields.forEach(function (primitive) {
                if (!primitive) {
                    return;
                }
                convertPrimitive(primitive);
                if (('start' in primitive
                        || 'end' in primitive
                        || 'type' in primitive)
                        && !sig.graph.edges(primitive.identity)) {
                    edgesMap[primitive.identity] = {
                        id : primitive.identity,
                        label : primitive.type,
                        source : primitive.start,
                        target : primitive.end,
                        color : '#7D7C8E',
                        neo4jType : primitive.type,
                        neo4jData : primitive.properties
                    };
                } else if (!sig.graph.nodes(primitive.identity)) {
                    nodesMap[primitive.identity] =  {
                        id : primitive.identity,
                        label : primitive.identity,
                        x : Math.random(),
                        y : Math.random(),
                        size : 1,
                        color : '#000000',
                        neo4jLabels : primitive.labels,
                        neo4jData : primitive.properties
                    };
                }
            });
        });

        // construct sigma nodes
        for (key in nodesMap) {
            graph.nodes.push(nodesMap[key]);
        }
        // construct sigma nodes
        for (key in edgesMap) {
            graph.edges.push(edgesMap[key]);
        }
        return graph;
    }

    //pass draw the graph
    var onResolve = function onResolve (response, addToGraph) {
        var graph = driverResultToSigmaGraph(response);
        if (!addToGraph) {//if it is invoked by queryStream method doesn't clear the graph
           sig.graph.clear();
        }
        sig.graph.read(graph);
        return sig;
    };

    /**
     * This function connect to neo4j via bolt connection and create the sigmajs object
     *
     * @param {object} neo4jOpts.   Options to pass to neo4j; defaults:
     * {
     *   endpoint : 'bolt://localhost',
     *   auth : { scheme : 'basic', principal : '<neo4j_connection_username>', password : '<neo4j_connection_password>' },
     *   version : 'v1'
     * }
     * @param {object} sigOpts.     Options to pass to sigma.js, see sigma.js docs for details.
     *
     * @return {Driver} A neo4j Driver object
     */
    sigma.neo4j.connect = function connect (neo4jOpts, sigOpts) {
    	if (arguments.length !== 2) {
    		throw 'You must define both neo4j and sigma options';
    	}
        version = neo4jOpts.version || 'v1';
        var endpoint = neo4jOpts.endpoint || 'bolt://localhost';
        var auth = !neo4jOpts.auth.scheme ?
                neo4j[version].auth.basic(neo4jOpts.auth.principal, neo4jOpts.auth.password) : neo4jOpts.auth;
        sig = new sigma(sigOpts);
        sig.refresh();
        driver = neo4j[version].driver(endpoint, auth);
        return driver;
    };

    /**
     * This function is for quering neo4j and draw the graph once the result is completly retrived
     *
     * @param {string} statement.   Neo4j Statement
     * @param {object} params.      Params of statement template
     *
     * @return {Promise} A Promise object
     */
    sigma.neo4j.query = function query (statement, params) {
    	return new Promise(function (resolve, reject) {
    		var session = driver.session();
            session.run(statement, params)
    			.then(function (response) {
                    resolve(onResolve(response));
                    session.close();
                })
    			.catch(reject);
    	});
    };

    /**
     * This function is for quering neo4j and draw the graph progressively
     * as records arrive by neo4j stream api
     *
     * @param {string} statement.   Neo4j Statement
     * @param {object} params.      Params of statement template
     *
     * @return {Promise} A Promise object
     */
    sigma.neo4j.queryStream = function queryStream (statement, params) {
    	return new Promise(function (resolve, reject) {
            var session = driver.session();
            session.run(statement, params)
                .subscribe({
                    onNext : function onNext (record) {
                        //console.log('onNext', record._fields);
                        onResolve({ records : [record] }, true);
                    },
                    onCompleted : function onCompleted () {
                        // Completed!
                        session.close();
                        resolve(sig);
                    },
                    onError : function onError (error) {
                        console.log('onError', error);
                        reject(error);
                    }
                });
        })
    };

    /**
     * This function collect all the node labels of the graph.
     *
     * @return {array} An array of labels
     */
    sigma.neo4j.getLabels = function() {
        return new Promise(function (resolve, reject) {
            var session = driver.session();
            session.run('match (n) with distinct labels(n) as labels unwind labels as label return label')
                .then(function (response) {
                    resolve(response.records.map(function (elem) { return elem._fields[0]; }));
                    session.close();
                })
                .catch(reject);

        });
    };

    /**
     * This function collect all the relationship types of the graph.
     *
     * @return {array} An array of relationships type
     */
    sigma.neo4j.getTypes = function() {
        return new Promise(function (resolve, reject) {
            var session = driver.session();
            session.run('match (n)-[r]-() return distinct type(r)')
                .then(function (response) {
                    resolve(response.records.map(function (elem) { return elem._fields[0]; }));
                    session.close();
                })
                .catch(reject);
        });
    };

}).call(this);

<commit_msg>Fix indentation<commit_after>;(function (undefined) {
    'use strict';

    if (typeof sigma === 'undefined') {
    	throw 'sigma is not declared';
    }

    if (!('Promise' in window)) {
    	throw 'Your browser must support Promise Object';
    }

    var driver = null,
        sig = null,
        version = null;

    // Declare neo4j package
    sigma.utils.pkg("sigma.neo4j");

    /*
     * Convert the Record object of neo4j bolt web driver in order to get
     * the integer value
     *
     * @param {Record} primitive.   The Record object returned by neo4j bolt web api.
     *
     */
    var convertPrimitive = function convertPrimitive (primitive) {
        var keys = Object.keys(primitive.properties);
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i],
                property = primitive.properties[key];
            if (typeof property === 'object'
                    && 'high' in property && 'low' in property) {
                property = property.low;
            }
        }
        primitive.identity = primitive.identity.low;
        if ('start' in primitive && 'end' in primitive) {
            primitive.start = primitive.start.low;
            primitive.end = primitive.end.low;
        }
    };

    /**
     * This function parse a neo4j cypher query result, and transform it into
     * a sigma graph object. (Inspired by sigma.neo4j.cypher plugin)
     *
     * @param {Result} response.   The Result object returned by neo4j bolt web api.
     *
     * @return {graph} Sigma.js Graph object
     */
    var driverResultToSigmaGraph = function driverResultToSigmaGraph (response) {
        var graph = { nodes: [], edges: [] },
            nodesMap = {},
            edgesMap = {},
            key;

        response.records.forEach(function (record) {
            record._fields.forEach(function (primitive) {
                if (!primitive) {
                    return;
                }
                convertPrimitive(primitive);
                if (('start' in primitive
                        || 'end' in primitive
                        || 'type' in primitive)
                        && !sig.graph.edges(primitive.identity)) {
                    edgesMap[primitive.identity] = {
                        id : primitive.identity,
                        label : primitive.type,
                        source : primitive.start,
                        target : primitive.end,
                        color : '#7D7C8E',
                        neo4jType : primitive.type,
                        neo4jData : primitive.properties
                    };
                } else if (!sig.graph.nodes(primitive.identity)) {
                    nodesMap[primitive.identity] =  {
                        id : primitive.identity,
                        label : primitive.identity,
                        x : Math.random(),
                        y : Math.random(),
                        size : 1,
                        color : '#000000',
                        neo4jLabels : primitive.labels,
                        neo4jData : primitive.properties
                    };
                }
            });
        });

        // construct sigma nodes
        for (key in nodesMap) {
            graph.nodes.push(nodesMap[key]);
        }
        // construct sigma nodes
        for (key in edgesMap) {
            graph.edges.push(edgesMap[key]);
        }
        return graph;
    }

    //pass draw the graph
    var onResolve = function onResolve (response, addToGraph) {
        var graph = driverResultToSigmaGraph(response);
        if (!addToGraph) {//if it is invoked by queryStream method doesn't clear the graph
           sig.graph.clear();
        }
        sig.graph.read(graph);
        return sig;
    };

    /**
     * This function connect to neo4j via bolt connection and create the sigmajs object
     *
     * @param {object} neo4jOpts.   Options to pass to neo4j; defaults:
     * {
     *   endpoint : 'bolt://localhost',
     *   auth : { scheme : 'basic', principal : '<neo4j_connection_username>', password : '<neo4j_connection_password>' },
     *   version : 'v1'
     * }
     * @param {object} sigOpts.     Options to pass to sigma.js, see sigma.js docs for details.
     *
     * @return {Driver} A neo4j Driver object
     */
    sigma.neo4j.connect = function connect (neo4jOpts, sigOpts) {
    	if (arguments.length !== 2) {
    		throw 'You must define both neo4j and sigma options';
    	}
        version = neo4jOpts.version || 'v1';
        var endpoint = neo4jOpts.endpoint || 'bolt://localhost';
        var auth = !neo4jOpts.auth.scheme ?
                neo4j[version].auth.basic(neo4jOpts.auth.principal, neo4jOpts.auth.password) : neo4jOpts.auth;
        sig = new sigma(sigOpts);
        sig.refresh();
        driver = neo4j[version].driver(endpoint, auth);
        return driver;
    };

    /**
     * This function is for quering neo4j and draw the graph once the result is completly retrived
     *
     * @param {string} statement.   Neo4j Statement
     * @param {object} params.      Params of statement template
     *
     * @return {Promise} A Promise object
     */
    sigma.neo4j.query = function query (statement, params) {
    	return new Promise(function (resolve, reject) {
    		var session = driver.session();
            session.run(statement, params)
    			.then(function (response) {
                    resolve(onResolve(response));
                    session.close();
                })
                .catch(reject);
    	});
    };

    /**
     * This function is for quering neo4j and draw the graph progressively
     * as records arrive by neo4j stream api
     *
     * @param {string} statement.   Neo4j Statement
     * @param {object} params.      Params of statement template
     *
     * @return {Promise} A Promise object
     */
    sigma.neo4j.queryStream = function queryStream (statement, params) {
    	return new Promise(function (resolve, reject) {
            var session = driver.session();
            session.run(statement, params)
                .subscribe({
                    onNext : function onNext (record) {
                        //console.log('onNext', record._fields);
                        onResolve({ records : [record] }, true);
                    },
                    onCompleted : function onCompleted () {
                        // Completed!
                        session.close();
                        resolve(sig);
                    },
                    onError : function onError (error) {
                        console.log('onError', error);
                        reject(error);
                    }
                });
        })
    };

    /**
     * This function collect all the node labels of the graph.
     *
     * @return {array} An array of labels
     */
    sigma.neo4j.getLabels = function() {
        return new Promise(function (resolve, reject) {
            var session = driver.session();
            session.run('match (n) with distinct labels(n) as labels unwind labels as label return label')
                .then(function (response) {
                    resolve(response.records.map(function (elem) { return elem._fields[0]; }));
                    session.close();
                })
                .catch(reject);

        });
    };

    /**
     * This function collect all the relationship types of the graph.
     *
     * @return {array} An array of relationships type
     */
    sigma.neo4j.getTypes = function() {
        return new Promise(function (resolve, reject) {
            var session = driver.session();
            session.run('match (n)-[r]-() return distinct type(r)')
                .then(function (response) {
                    resolve(response.records.map(function (elem) { return elem._fields[0]; }));
                    session.close();
                })
                .catch(reject);
        });
    };

}).call(this);

<|endoftext|>


<commit_before>/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 *
 * 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.
 */

// Eslint configuration for editor.
/* globals google */
/* eslint-env browser */
/* eslint quotes: ["warn", "single"]*/

function initMap() {
    const map = new google.maps.Map(document.getElementsByClassName('map')[0], {
        zoom: 11,
        center: {
            lat: 40.7305,
            lng: -73.9091
        }
    });
    map.data.loadGeoJson('/data/subway-stations');
    map.data.loadGeoJson('/data/subway-lines');
}<commit_msg>Update step-04/app.js<commit_after>/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 *
 * 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.
 */

// Eslint configuration for editor.
/* globals google */
/* eslint-env browser */
/* eslint quotes: ["warn", "single"]*/

function initMap() {
    const map = new google.maps.Map(document.getElementsByClassName('map')[0], {
        zoom: 11,
        center: {
            // New York City
            lat: 40.7305,
            lng: -73.9091
        }
    });
    map.data.loadGeoJson('/data/subway-stations');
    map.data.loadGeoJson('/data/subway-lines');
}
<|endoftext|>


<commit_before><commit_msg>draw mismatches in zoomed out view<commit_after><|endoftext|>


<commit_before>/**
 * Created by yangm11 on 10/17/2018.
 */

/******************************************************************************
 * ngram query examples
 * 1. [display()].from(bioactivity).usingschema(schema.bioactivity)
 * 2. [display(),hist(aidtype,actvty)].from(bioactivity).usingschema(schema.bioactivity)
 * 3. [display(sid,acname,acvalue,actvty,cid,cmpdname,aid,aidtype,aidname,protdefline,gi,pmid)].from(bioactivity).usingschema(schema.bioactivity).matching(aid==1)
 * 4. [display(sid,acname,acvalue,actvty,cid,cmpdname,aid,aidtype,aidname,protdefline,gi,pmid)].from(bioactivity).usingschema(schema.bioactivity).matching(aid in [1,3,5])
 * 5. [display()].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244)
 * 6. [display()].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244 && actvty==active)
 * 7. [display(),hist(actvty,genename,acname,aidtype)].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244&&actvty==active)
 *****************************************************************************/

'use strict';

class NgParser {
  constructor() {}
  parse(s) {

  }
  static split(s) {
    s = s.toLowerCase().trim();
    let group = {
      '[': 0,
      '(': 0
    };
    let res = [];
    let sub = '';
    let i = 0;
    let j = s.length;
    while (i < j) {
      let c = s[i];
      switch (c) {
        case '.':
          if (group['['] === 0 && group['('] === 0) {
            res.push(sub);
            sub = '';
          } else {
            sub += c;
          }
          break;
        case '[':
          group['['] += 1;
          sub += c;
          break;
        case ']':
          group['['] -= 1;
          sub += c;
          break;
        case '(':
          group['('] += 1;
          sub += c;
          break;
        case ')':
          group['('] -= 1;
          sub += c;
          break;
        default:
          sub += c;
      }
      i++;
    }
    return res;
  }
  static splitArray(s) {

  }
  static parse(s) {
    const verbs = ['display', 'from', 'usingschema', 'matching', 'hist'];
    s = s.toLowerCase().trim();
    let i = s.indexOf('(');
    if (i === -1 || s[s.length-1] !== ')') {
      return [new Error('invalid format: incomplete parenthesis'), null];
    }
    let verb = s.slice(0, i);
    if (verbs.indexOf(verb) === -1) {
      return [new Error('invalid verb: ' + verb), null];
    }
    return [null, {
      verb: verb,
      args: s.slice(i+1, -1).split(',').filter(d => !!d.length)
    }];
  }
}

if (typeof module !== 'undefined') {
  // Node environment,
  if (module.parent) {
    // required as module

  } else {
    // run as executable

    let s = '[display(),hist(actvty,genename,acname,aidtype)].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244&&actvty==active)';
    console.log(NgParser.split(s));

  }
} else if (typeof window === 'object') {
  // Browser environment
} <commit_msg>ngram parser done<commit_after>/**
 * Created by yangm11 on 10/17/2018.
 */

/******************************************************************************
 * ngram query examples
 * 1. [display()].from(bioactivity).usingschema(schema.bioactivity)
 * 2. [display(),hist(aidtype,actvty)].from(bioactivity).usingschema(schema.bioactivity)
 * 3. [display(sid,acname,acvalue,actvty,cid,cmpdname,aid,aidtype,aidname,protdefline,gi,pmid)].from(bioactivity).usingschema(schema.bioactivity).matching(aid==1)
 * 4. [display(sid,acname,acvalue,actvty,cid,cmpdname,aid,aidtype,aidname,protdefline,gi,pmid)].from(bioactivity).usingschema(schema.bioactivity).matching(aid in [1,3,5])
 * 5. [display()].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244)
 * 6. [display()].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244 && actvty==active)
 * 7. [display(),hist(actvty,genename,acname,aidtype)].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244&&actvty==active)
 *****************************************************************************/

'use strict';

class NgParser {
  constructor() {}
  parse(s) {
    let a = NgParser.split(s);
    let res = [];
    for (let i = 0; i < a.length; i++) {
      let s = a[i];
      let v;
      if (s[0] === '[') {
        v = NgParser.splitArray(s);
      } else {
        v = NgParser.parse(s);
      }
      if (v[0] === null) {
        if (Array.isArray(v[1])) {
          let t = NgParser.parseArray(v[1]);
          if (t[0] !== null) {
            return [t[0], null];
          }
          res.push(t[1]);
        } else {
          res.push(v[1]);
        }
      } else {
        return [v[0], null];
      }
    }
    return [null, res];
  }
  static split(s) {
    s = s.toLowerCase().trim();
    let group = {
      '[': 0,
      '(': 0
    };
    let res = [];
    let sub = '';
    let i = 0;
    let j = s.length;
    while (i < j) {
      let c = s[i];
      switch (c) {
        case '.':
          if (group['['] === 0 && group['('] === 0) {
            res.push(sub);
            sub = '';
          } else {
            sub += c;
          }
          break;
        case '[':
          group['['] += 1;
          sub += c;
          break;
        case ']':
          group['['] -= 1;
          sub += c;
          break;
        case '(':
          group['('] += 1;
          sub += c;
          break;
        case ')':
          group['('] -= 1;
          sub += c;
          break;
        default:
          sub += c;
      }
      i++;
    }
    res.push(sub);
    return res;
  }
  static splitArray(s) {
    s = s.toLowerCase().trim();
    if (s[0] !== '[' || s[s.length-1] !== ']') {
      return [new Error('invalide array format'), null];
    }
    let group = 0;
    let sub = '';
    let res = [];
    let i = 1;
    let j = s.length-1;
    while (i < j) {
      switch (s[i]) {
        case ',':
          if (group === 0) {
            res.push(sub);
            sub = '';
          } else {
            sub += s[i];
          }
          break;
        case '(':
          group++;
          sub += s[i];
          break;
        case ')':
          group--;
          sub += s[i];
          break;
        default:
          sub += s[i];
      }
      i++;
    }
    res.push(sub);
    return [null, res];
  }

  // parse a block
  static parse(s) {
    const verbs = ['display', 'from', 'usingschema', 'matching', 'hist'];
    s = s.toLowerCase().trim();
    let i = s.indexOf('(');
    if (i === -1 || s[s.length-1] !== ')') {
      return [new Error('invalid format: incomplete parenthesis'), null];
    }
    let verb = s.slice(0, i);
    if (verbs.indexOf(verb) === -1) {
      return [new Error('invalid verb: ' + verb), null];
    }
    return [null, {
      verb: verb,
      args: s.slice(i+1, -1).split(',').filter(d => !!d.length)
    }];
  }

  // parse a list of blocks
  static parseArray(a) {
    let res = [];
    for (let j = 0; j < a.length; j++) {
      let o = NgParser.parse(a[j]);
      if (o[0] !== null) {
        return [o[0], null];
      } else {
        res.push(o[1]);
      }
    }
    return [null, res];
  }
}

if (typeof module !== 'undefined') {
  // Node environment,
  if (module.parent) {
    // required as module

  } else {
    // run as executable

    let s = '[display(),hist(actvty,genename,acname,aidtype)].from(bioactivity).usingschema(schema.bioactivity).matching(cid==2244&&actvty==active)';
    console.log(NgParser.split(s));
    let s1 = '[display(),hist(actvty,genename,acname,aidtype)]';
    console.log(NgParser.splitArray(s1));

    let ng = new NgParser();
    console.dir(ng.parse(s), {depth: null, colors: true});

  }
} else if (typeof window === 'object') {
  // Browser environment
} <|endoftext|>


<commit_before><commit_msg>[server] Update sender column<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

define(['js/Constants',
    'js/NodePropertyNames',
    'js/RegistryKeys',
    'js/Utils/DisplayFormat',
    'js/Widgets/DiagramDesigner/DiagramDesignerWidget.Constants',
    'text!./default.svg'], function (CONSTANTS,
                         nodePropertyNames,
                         REGISTRY_KEYS,
                         displayFormat,
                         DiagramDesignerWidgetConstants,
                         DefaultSvgTemplate) {

    var SVGDecoratorCore,
        ABSTRACT_CLASS = 'abstract',
        SVG_DIR = '/decorators/SVGDecorator/SVG/',
        CONNECTION_AREA_CLASS = 'connection-area',
        DATA_LEN = 'len',
        DATA_ANGLE = 'angle',
        DATA_ANGLE1 = 'angle1',
        DATA_ANGLE2 = 'angle2',
        DEFAULT_STEM_LENGTH = 20,
        FILL_COLOR_CLASS = "fill-color",
        BORDER_COLOR_CLASS = "border-color",
        TEXT_COLOR_CLASS = "text-color";

    /**
     * Contains downloaded svg elements from the server.
     * @type {{}}
     * @private
     */
    var svgCache = {};

    /**
     * Svg element that can be used as a placeholder for the icon if the icon does not exist on the server.
     * @type {*|jQuery|HTMLElement}
     * @private
     */
    var defaultSVG = $(DefaultSvgTemplate);

    SVGDecoratorCore = function () {
    };

    SVGDecoratorCore.prototype._initializeVariables = function (params) {
        this.name = "";
        this.formattedName = "";
        this.$name = undefined;

		this._displayConnectors = false;
		if (params && params.connectors) {
			this._displayConnectors = params.connectors;
		}
    };

    /**** Override from *.WidgetDecoratorBase ****/
    SVGDecoratorCore.prototype.doSearch = function (searchDesc) {
        var searchText = searchDesc.toString().toLowerCase();

        return (this.formattedName && this.formattedName.toLowerCase().indexOf(searchText) !== -1);
    };

    SVGDecoratorCore.prototype._renderContent = function () {
        //render GME-ID in the DOM, for debugging
        this.$el.attr({"data-id": this._metaInfo[CONSTANTS.GME_ID]});

        /* BUILD UI*/
        //find placeholders
        this.$name = this.$el.find(".name");
        this.$svgContent = this.$el.find(".svg-content");

		this._update();
    };

	SVGDecoratorCore.prototype._update = function () {
        this._updateSVGFile();
        this._updateColors();
        this._updateName();
        this._updateAbstract();
    };

    SVGDecoratorCore.prototype._updateColors = function () {
        var svg = this.$svgContent.find('svg'),
            fillColorElements = svg.find('.' + FILL_COLOR_CLASS),
            borderColorElements = svg.find('.' + BORDER_COLOR_CLASS),
            textColorElements = svg.find('.' + TEXT_COLOR_CLASS);

        this._getNodeColorsFromRegistry();

        if (this.fillColor) {
            fillColorElements.css({'fill': this.fillColor});
        } else {
            this.$el.css({'fill': ''});
        }

        if (this.borderColor) {
            borderColorElements.css({'stroke': this.borderColor});
        } else {
            borderColorElements.css({'stroke': ''});
        }

        if (this.textColor) {
            this.$el.css({'color': this.textColor});
            textColorElements.css({'fill': this.textColor});
        } else {
            this.$el.css({'color': ''});
            textColorElements.css({'fill': ''});
        }
    };

    SVGDecoratorCore.prototype._getNodeColorsFromRegistry = function () {
        var objID = this._metaInfo[CONSTANTS.GME_ID];
        this.fillColor = this.preferencesHelper.getRegistry(objID, REGISTRY_KEYS.COLOR, true);
        this.borderColor = this.preferencesHelper.getRegistry(objID, REGISTRY_KEYS.BORDER_COLOR, true);
        this.textColor = this.preferencesHelper.getRegistry(objID, REGISTRY_KEYS.TEXT_COLOR, true);
    };

    /***** UPDATE THE NAME OF THE NODE *****/
    SVGDecoratorCore.prototype._updateName = function () {
        var client = this._control._client,
            nodeObj = client.getNode(this._metaInfo[CONSTANTS.GME_ID]),
            noName = "(N/A)";

        if (nodeObj) {
            this.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name);
            this.formattedName = displayFormat.resolve(nodeObj);
        } else {
            this.name = "";
            this.formattedName = noName;
        }

        this.$name.text(this.formattedName);
        this.$name.attr("title", this.formattedName);
    };

    /***** UPDATE THE ABSTRACTNESS OF THE NODE *****/
    SVGDecoratorCore.prototype._updateAbstract = function () {
        var client = this._control._client,
            nodeObj = client.getNode(this._metaInfo[CONSTANTS.GME_ID]);

        if (nodeObj) {
            if (nodeObj.getRegistry(REGISTRY_KEYS.IS_ABSTRACT) === true) {
                this.$el.addClass(ABSTRACT_CLASS);
            } else {
                this.$el.removeClass(ABSTRACT_CLASS);
            }
        } else {
            this.$el.removeClass(ABSTRACT_CLASS);
        }
    };

    /***** UPDATE THE SVG ICON OF THE NODE *****/
    SVGDecoratorCore.prototype._updateSVGFile = function () {
        var client = this._control._client,
            nodeObj = client.getNode(this._metaInfo[CONSTANTS.GME_ID]),
            svgFile = "",
            svgURL,
            self = this,
            logger = this.logger;

        if (nodeObj) {
            svgFile = nodeObj.getAttribute('svg');
        }

        if (svgFile) {
            if (svgCache[svgFile]) {
                this._updateSVGContent(svgFile);
            } else {
                // get the svg from the server in SYNC mode, may take some time
                svgURL = SVG_DIR + svgFile;
                $.ajax(svgURL, {'async': false})
                    .done(function ( data ) {
                        // downloaded successfully
                        // cache the content
                        svgCache[svgFile] = $(data.childNodes[0]);
                        self._updateSVGContent(svgFile);
                    })
                    .fail(function () {
                        // download failed for this type
                        logger.error('Failed to download SVG file: ' + svgFile);
                        self._updateSVGContent(svgFile);
                    });
            }
        } else {
            this._updateSVGContent(undefined);
        }

    };

    SVGDecoratorCore.prototype._getSVGContent = function (svgFile) {
        if (svgCache[svgFile]) {
            return svgCache[svgFile].clone();
        } else {
            return defaultSVG.clone();
        }
    };

    SVGDecoratorCore.prototype._updateSVGContent = function (svg) {
        //set new content
        this.$svgContent.empty();
        this.$svgContent.append(this._getSVGContent(svg));

        this._discoverConnectionAreas();
        this._generateConnectors();
    };

    SVGDecoratorCore.prototype._discoverConnectionAreas = function () {
        var connAreas = this.$svgContent.find('svg').find('.' + CONNECTION_AREA_CLASS),
            len = connAreas.length,
            line,
            connA,
            lineData,
            dx,
            dy,
            alpha;

        delete this._customConnectionAreas;

        if (len > 0) {
            this._customConnectionAreas = [];

            while (len--) {
                line = $(connAreas[len]);
                connA = {"id": line.attr('id'),
                    "x1": parseInt(line.attr('x1'), 10),
                    "y1": parseInt(line.attr('y1'), 10),
                    "x2": parseInt(line.attr('x2'), 10),
                    "y2": parseInt(line.attr('y2'), 10),
                    "angle1": 0,
                    "angle2": 0,
                    "len": DEFAULT_STEM_LENGTH};

                //try to figure out meta info from the embedded SVG
                lineData = line.data();

                if (lineData.hasOwnProperty(DATA_LEN)) {
                    connA.len = parseInt(lineData[DATA_LEN], 10);
                }

                if (lineData.hasOwnProperty(DATA_ANGLE)) {
                    connA.angle1 = parseInt(lineData[DATA_ANGLE], 10);
                    connA.angle2 = parseInt(lineData[DATA_ANGLE], 10);
                }

                if (lineData.hasOwnProperty(DATA_ANGLE1)) {
                    connA.angle1 = parseInt(lineData[DATA_ANGLE1], 10);
                }

                if (lineData.hasOwnProperty(DATA_ANGLE2)) {
                    connA.angle2 = parseInt(lineData[DATA_ANGLE2], 10);
                }

                if (!lineData.hasOwnProperty(DATA_ANGLE) &&
                    !(lineData.hasOwnProperty(DATA_ANGLE1) && lineData.hasOwnProperty(DATA_ANGLE2))) {
                    dx = connA.x2 - connA.x1;
                    dy = connA.y2 - connA.y1;
                    if (dx !== 0 && dy !== 0) {
                        alpha = Math.atan(dy / dx) * (180/Math.PI);
                        if (dx > 0) {
                            alpha = 270 + alpha;
                        } else if (dx < 0) {
                            alpha = 90 + alpha;
                        }
                    } else if (dx === 0 && dy !== 0) {
                        //conn area is vertical
                        alpha = dy > 0 ? 0 : 180;
                    } else if (dx !== 0 && dy === 0) {
                        //conn area is horizontal
                        alpha = dx > 0 ? 270 : 90;
                    }

                    connA.angle1 = alpha;
                    connA.angle2 = alpha;
                }

                this._customConnectionAreas.push(connA);

                //finally remove the placeholder from the SVG
                line.remove();
            }
        }

    };

    SVGDecoratorCore.prototype._generateConnectors = function () {
        var connectors = this.$svgContent.find('svg').find('.' + DiagramDesignerWidgetConstants.CONNECTOR_CLASS),
            c,
            svg = this.$svgContent.find('svg'),
            svgWidth = parseInt(svg.attr('width'), 10),
            svgHeight = parseInt(svg.attr('height'), 10);

        if (this._displayConnectors === true) {
            //check if there are any connectors defined in the SVG itself
            if (connectors.length === 0) {
                //no dedicated connectors
                //by default generate four: N, S, E, W

                //NORTH
                c = $('<div/>', { class: 'connector' });
                c.css({'top': 0,
                       'left': svgWidth / 2});
                this.$el.append(c);

                //SOUTH
                c = $('<div/>', { class: 'connector' });
                c.css({'top': svgHeight,
                       'left': svgWidth / 2});
                this.$el.append(c);

                //EAST
                c = $('<div/>', { class: 'connector' });
                c.css({'top': svgHeight / 2,
                       'left': svgWidth});
                this.$el.append(c);

                //WEST
                c = $('<div/>', { class: 'connector' });
                c.css({'top': svgHeight / 2,
                    'left': 0});
                this.$el.append(c);
            }

            this.initializeConnectors();
        } else {
            connectors.remove();
        }
    };

    return SVGDecoratorCore;
});<commit_msg>bugfix: remove old connectors before creating new ones<commit_after>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

define(['js/Constants',
    'js/NodePropertyNames',
    'js/RegistryKeys',
    'js/Utils/DisplayFormat',
    'js/Widgets/DiagramDesigner/DiagramDesignerWidget.Constants',
    'text!./default.svg'], function (CONSTANTS,
                         nodePropertyNames,
                         REGISTRY_KEYS,
                         displayFormat,
                         DiagramDesignerWidgetConstants,
                         DefaultSvgTemplate) {

    var SVGDecoratorCore,
        ABSTRACT_CLASS = 'abstract',
        SVG_DIR = '/decorators/SVGDecorator/SVG/',
        CONNECTION_AREA_CLASS = 'connection-area',
        DATA_LEN = 'len',
        DATA_ANGLE = 'angle',
        DATA_ANGLE1 = 'angle1',
        DATA_ANGLE2 = 'angle2',
        DEFAULT_STEM_LENGTH = 20,
        FILL_COLOR_CLASS = "fill-color",
        BORDER_COLOR_CLASS = "border-color",
        TEXT_COLOR_CLASS = "text-color";

    /**
     * Contains downloaded svg elements from the server.
     * @type {{}}
     * @private
     */
    var svgCache = {};

    /**
     * Svg element that can be used as a placeholder for the icon if the icon does not exist on the server.
     * @type {*|jQuery|HTMLElement}
     * @private
     */
    var defaultSVG = $(DefaultSvgTemplate);

    SVGDecoratorCore = function () {
    };

    SVGDecoratorCore.prototype._initializeVariables = function (params) {
        this.name = "";
        this.formattedName = "";
        this.$name = undefined;

		this._displayConnectors = false;
		if (params && params.connectors) {
			this._displayConnectors = params.connectors;
		}
    };

    /**** Override from *.WidgetDecoratorBase ****/
    SVGDecoratorCore.prototype.doSearch = function (searchDesc) {
        var searchText = searchDesc.toString().toLowerCase();

        return (this.formattedName && this.formattedName.toLowerCase().indexOf(searchText) !== -1);
    };

    SVGDecoratorCore.prototype._renderContent = function () {
        //render GME-ID in the DOM, for debugging
        this.$el.attr({"data-id": this._metaInfo[CONSTANTS.GME_ID]});

        /* BUILD UI*/
        //find placeholders
        this.$name = this.$el.find(".name");
        this.$svgContent = this.$el.find(".svg-content");

		this._update();
    };

	SVGDecoratorCore.prototype._update = function () {
        this._updateSVGFile();
        this._updateColors();
        this._updateName();
        this._updateAbstract();
    };

    SVGDecoratorCore.prototype._updateColors = function () {
        var svg = this.$svgContent.find('svg'),
            fillColorElements = svg.find('.' + FILL_COLOR_CLASS),
            borderColorElements = svg.find('.' + BORDER_COLOR_CLASS),
            textColorElements = svg.find('.' + TEXT_COLOR_CLASS);

        this._getNodeColorsFromRegistry();

        if (this.fillColor) {
            fillColorElements.css({'fill': this.fillColor});
        } else {
            this.$el.css({'fill': ''});
        }

        if (this.borderColor) {
            borderColorElements.css({'stroke': this.borderColor});
        } else {
            borderColorElements.css({'stroke': ''});
        }

        if (this.textColor) {
            this.$el.css({'color': this.textColor});
            textColorElements.css({'fill': this.textColor});
        } else {
            this.$el.css({'color': ''});
            textColorElements.css({'fill': ''});
        }
    };

    SVGDecoratorCore.prototype._getNodeColorsFromRegistry = function () {
        var objID = this._metaInfo[CONSTANTS.GME_ID];
        this.fillColor = this.preferencesHelper.getRegistry(objID, REGISTRY_KEYS.COLOR, true);
        this.borderColor = this.preferencesHelper.getRegistry(objID, REGISTRY_KEYS.BORDER_COLOR, true);
        this.textColor = this.preferencesHelper.getRegistry(objID, REGISTRY_KEYS.TEXT_COLOR, true);
    };

    /***** UPDATE THE NAME OF THE NODE *****/
    SVGDecoratorCore.prototype._updateName = function () {
        var client = this._control._client,
            nodeObj = client.getNode(this._metaInfo[CONSTANTS.GME_ID]),
            noName = "(N/A)";

        if (nodeObj) {
            this.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name);
            this.formattedName = displayFormat.resolve(nodeObj);
        } else {
            this.name = "";
            this.formattedName = noName;
        }

        this.$name.text(this.formattedName);
        this.$name.attr("title", this.formattedName);
    };

    /***** UPDATE THE ABSTRACTNESS OF THE NODE *****/
    SVGDecoratorCore.prototype._updateAbstract = function () {
        var client = this._control._client,
            nodeObj = client.getNode(this._metaInfo[CONSTANTS.GME_ID]);

        if (nodeObj) {
            if (nodeObj.getRegistry(REGISTRY_KEYS.IS_ABSTRACT) === true) {
                this.$el.addClass(ABSTRACT_CLASS);
            } else {
                this.$el.removeClass(ABSTRACT_CLASS);
            }
        } else {
            this.$el.removeClass(ABSTRACT_CLASS);
        }
    };

    /***** UPDATE THE SVG ICON OF THE NODE *****/
    SVGDecoratorCore.prototype._updateSVGFile = function () {
        var client = this._control._client,
            nodeObj = client.getNode(this._metaInfo[CONSTANTS.GME_ID]),
            svgFile = "",
            svgURL,
            self = this,
            logger = this.logger;

        if (nodeObj) {
            svgFile = nodeObj.getAttribute('svg');
        }

        if (svgFile) {
            if (svgCache[svgFile]) {
                this._updateSVGContent(svgFile);
            } else {
                // get the svg from the server in SYNC mode, may take some time
                svgURL = SVG_DIR + svgFile;
                $.ajax(svgURL, {'async': false})
                    .done(function ( data ) {
                        // downloaded successfully
                        // cache the content
                        svgCache[svgFile] = $(data.childNodes[0]);
                        self._updateSVGContent(svgFile);
                    })
                    .fail(function () {
                        // download failed for this type
                        logger.error('Failed to download SVG file: ' + svgFile);
                        self._updateSVGContent(svgFile);
                    });
            }
        } else {
            this._updateSVGContent(undefined);
        }

    };

    SVGDecoratorCore.prototype._getSVGContent = function (svgFile) {
        if (svgCache[svgFile]) {
            return svgCache[svgFile].clone();
        } else {
            return defaultSVG.clone();
        }
    };

    SVGDecoratorCore.prototype._updateSVGContent = function (svg) {
        //set new content
        this.$svgContent.empty();
        this.$svgContent.append(this._getSVGContent(svg));

        this._discoverConnectionAreas();
        this._generateConnectors();
    };

    SVGDecoratorCore.prototype._discoverConnectionAreas = function () {
        var connAreas = this.$svgContent.find('svg').find('.' + CONNECTION_AREA_CLASS),
            len = connAreas.length,
            line,
            connA,
            lineData,
            dx,
            dy,
            alpha;

        delete this._customConnectionAreas;

        if (len > 0) {
            this._customConnectionAreas = [];

            while (len--) {
                line = $(connAreas[len]);
                connA = {"id": line.attr('id'),
                    "x1": parseInt(line.attr('x1'), 10),
                    "y1": parseInt(line.attr('y1'), 10),
                    "x2": parseInt(line.attr('x2'), 10),
                    "y2": parseInt(line.attr('y2'), 10),
                    "angle1": 0,
                    "angle2": 0,
                    "len": DEFAULT_STEM_LENGTH};

                //try to figure out meta info from the embedded SVG
                lineData = line.data();

                if (lineData.hasOwnProperty(DATA_LEN)) {
                    connA.len = parseInt(lineData[DATA_LEN], 10);
                }

                if (lineData.hasOwnProperty(DATA_ANGLE)) {
                    connA.angle1 = parseInt(lineData[DATA_ANGLE], 10);
                    connA.angle2 = parseInt(lineData[DATA_ANGLE], 10);
                }

                if (lineData.hasOwnProperty(DATA_ANGLE1)) {
                    connA.angle1 = parseInt(lineData[DATA_ANGLE1], 10);
                }

                if (lineData.hasOwnProperty(DATA_ANGLE2)) {
                    connA.angle2 = parseInt(lineData[DATA_ANGLE2], 10);
                }

                if (!lineData.hasOwnProperty(DATA_ANGLE) &&
                    !(lineData.hasOwnProperty(DATA_ANGLE1) && lineData.hasOwnProperty(DATA_ANGLE2))) {
                    dx = connA.x2 - connA.x1;
                    dy = connA.y2 - connA.y1;
                    if (dx !== 0 && dy !== 0) {
                        alpha = Math.atan(dy / dx) * (180/Math.PI);
                        if (dx > 0) {
                            alpha = 270 + alpha;
                        } else if (dx < 0) {
                            alpha = 90 + alpha;
                        }
                    } else if (dx === 0 && dy !== 0) {
                        //conn area is vertical
                        alpha = dy > 0 ? 0 : 180;
                    } else if (dx !== 0 && dy === 0) {
                        //conn area is horizontal
                        alpha = dx > 0 ? 270 : 90;
                    }

                    connA.angle1 = alpha;
                    connA.angle2 = alpha;
                }

                this._customConnectionAreas.push(connA);

                //finally remove the placeholder from the SVG
                line.remove();
            }
        }

    };

    SVGDecoratorCore.prototype._generateConnectors = function () {
        var connectors = this.$svgContent.find('svg').find('.' + DiagramDesignerWidgetConstants.CONNECTOR_CLASS),
            c,
            svg = this.$svgContent.find('svg'),
            svgWidth = parseInt(svg.attr('width'), 10),
            svgHeight = parseInt(svg.attr('height'), 10);

        //remove existing ones
        this.$el.find('.' + DiagramDesignerWidgetConstants.CONNECTOR_CLASS).remove();

        if (this._displayConnectors === true) {
            //check if there are any connectors defined in the SVG itself
            if (connectors.length === 0) {
                //no dedicated connectors
                //by default generate four: N, S, E, W

                //NORTH
                c = $('<div/>', { class: 'connector' });
                c.css({'top': 0,
                       'left': svgWidth / 2});
                this.$el.append(c);

                //SOUTH
                c = $('<div/>', { class: 'connector' });
                c.css({'top': svgHeight,
                       'left': svgWidth / 2});
                this.$el.append(c);

                //EAST
                c = $('<div/>', { class: 'connector' });
                c.css({'top': svgHeight / 2,
                       'left': svgWidth});
                this.$el.append(c);

                //WEST
                c = $('<div/>', { class: 'connector' });
                c.css({'top': svgHeight / 2,
                    'left': 0});
                this.$el.append(c);
            }

            this.initializeConnectors();
        } else {
            connectors.remove();
        }
    };

    return SVGDecoratorCore;
});<|endoftext|>


<commit_before>define([
  'text!./cam-tasklist-filters.html',
  'angular'
], function(
  template,
  angular
) {
  'use strict';
  var $ = angular.element;
  var each = angular.forEach;

  return [function() {

    return {

      restrict: 'EAC',
      scope: {
        tasklistData: '='
      },

      template: template,

      controller: [
        '$scope',
        '$q',
        'camAPI',
      function (
        $scope,
        $q,
        camAPI
      ) {

        var Filter = camAPI.resource('filter');
        var filtersData = $scope.filtersData = $scope.tasklistData.newChild($scope);
        var query;

        /**
         * observe list of filters and pre-process
         */
        $scope.state = filtersData.observe(['filters', 'taskListQuery', function(filters, taskListQuery) {

          $scope.totalItems = filters.length;

          var focused,
              filterId = query.id;

          for (var i = 0, filter; !!(filter = filters[i]); i++) {
            // read background color from properties
            filter.style = {
              'background-color': filter.properties.color
            };

            if (filterId) {
              if (filterId === filter.id) {
                focused = filter;
                break;
              }
            }
            else {
              // auto focus first filter
              if(!focused || filter.properties.priority < focused.properties.priority) {
                focused = filter;
              }
            }
          }

          $scope.filters = filters;
          $scope.focus(focused);

        }]);

        /**
         * observe the count for the current filter
         */
        filtersData.observe('taskList', function(taskList) {
          $scope.filterCount = taskList.count;
        });

        /**
         * observe the count for the current filter
         */
        filtersData.observe('taskListQuery', function(taskListQuery) {
          query = taskListQuery;
        });

        /**
         * observe list of filters to set the background-color on a filter
         */
        $scope.state = filtersData.observe('filters', function(filters) {

          $scope.totalItems = filters.length;

          for (var i = 0, filter; !!(filter = filters[i]); i++) {
            // read background color from properties
            filter.style = {
              'background-color': filter.properties.color
            };

          }

          $scope.filters = filters;

        });

        /**
         * observe list of filters and taskListQuery to set the focus
         */
        $scope.state = filtersData.observe(['filters', 'taskListQuery', function(filters, taskListQuery) {

          var focused,
              filterId = query.id;

          for (var i = 0, filter; !!(filter = filters[i]); i++) {

            if (filterId) {
              if (filterId === filter.id) {
                focused = filter;
                break;
              }
            }
            else {
              // auto focus first filter
              if(!focused || filter.properties.priority < focused.properties.priority) {
                focused = filter;
              }
            }
          }

          $scope.focus(focused);

        }]);

        /**
         * select a filter
         */
        $scope.focus = function(filter) {
          $scope.filterCount = undefined;

          if (filter) {

            if(filter.id !== query.id) {
              // filter changed => reset pagination
              query.firstResult = 0;
            }
            query.id = filter.id;

          }
          else {
            query.id = null;

          }

          filtersData.set('taskListQuery', angular.copy(query));
        };

        /**
         * returns true if the provided filter is the focused filter
         */
        $scope.isFocused = function(filter) {
          return filter.id === query.id;
        };

      }]
    };
  }];
});
<commit_msg>chore(filters): clean up code<commit_after>define([
  'text!./cam-tasklist-filters.html',
  'angular'
], function(
  template,
  angular
) {
  'use strict';
  var $ = angular.element;
  var each = angular.forEach;

  return [function() {

    return {

      restrict: 'EAC',
      scope: {
        tasklistData: '='
      },

      template: template,

      controller: [
        '$scope',
        '$q',
        'camAPI',
      function (
        $scope,
        $q,
        camAPI
      ) {

        var Filter = camAPI.resource('filter');
        var filtersData = $scope.filtersData = $scope.tasklistData.newChild($scope);
        var query;

        /**
         * observe the count for the current filter
         */
        filtersData.observe('taskList', function(taskList) {
          $scope.filterCount = taskList.count;
        });

        /**
         * observe the count for the current filter
         */
        filtersData.observe('taskListQuery', function(taskListQuery) {
          query = taskListQuery;
        });

        /**
         * observe list of filters to set the background-color on a filter
         */
        $scope.state = filtersData.observe('filters', function(filters) {

          $scope.totalItems = filters.length;

          for (var i = 0, filter; !!(filter = filters[i]); i++) {
            // read background color from properties
            filter.style = {
              'background-color': filter.properties.color
            };

          }

          $scope.filters = filters;

        });

        /**
         * observe list of filters and taskListQuery to set the focus
         */
        $scope.state = filtersData.observe(['filters', 'taskListQuery', function(filters, taskListQuery) {

          var focused,
              filterId = query.id;

          for (var i = 0, filter; !!(filter = filters[i]); i++) {

            if (filterId) {
              if (filterId === filter.id) {
                focused = filter;
                break;
              }
            }
            else {
              // auto focus first filter
              if(!focused || filter.properties.priority < focused.properties.priority) {
                focused = filter;
              }
            }
          }

          $scope.focus(focused);

        }]);

        /**
         * select a filter
         */
        $scope.focus = function(filter) {
          $scope.filterCount = undefined;

          if (filter) {

            if(filter.id !== query.id) {
              // filter changed => reset pagination
              query.firstResult = 0;
            }
            query.id = filter.id;

          }
          else {
            query.id = null;

          }

          filtersData.set('taskListQuery', angular.copy(query));
        };

        /**
         * returns true if the provided filter is the focused filter
         */
        $scope.isFocused = function(filter) {
          return filter.id === query.id;
        };

      }]
    };
  }];
});
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import AssetUploadButton from './AssetUploadButton.js'
import Studio, { TextEditor } from 'jsreport-studio'

export default class FileEditor extends Component {
  constructor () {
    super()
    this.state = { isMetaView: true }
  }

  async openEditor () {
    const { entity } = this.props

    var content = entity.content
    if (entity.link && !entity.content && !this.state.loadFailed) {
      try {
        content = btoa(await Studio.api.get(`assets/${encodeURIComponent(entity.name)}`, { parseJSON: false }))
      } catch (e) {
        this.setState({ loadFailed: true })
        throw e
      }
    }

    this.setState({ isMetaView: false, content: content })
  }

  async componentDidUpdate (prevProps) {
    const { entity } = this.props

    if (entity.link && (!this.state.link || prevProps.entity.link !== entity.link) && !this.state.loadFailed) {
      try {
        const link = await Studio.api.get(`assets/link/${encodeURIComponent(entity.link)}`, { parseJSON: false })
        this.setState({ link: link })
      } catch (e) {
        this.setState({ loadFailed: true })
        throw e
      }
    }
  }

  render () {
    const { entity, onUpdate } = this.props
    const { isMetaView, content, link } = this.state
    const downloadUrl = Studio.resolveUrl(`assets/${encodeURIComponent(entity.name)}?download=true`)
    let mode = 'text'
    if (entity.name.includes('.js')) {
      mode = 'javascript'
    }

    if (entity.name.includes('.css')) {
      mode = 'css'
    }

    if (entity.name.includes('.html')) {
      mode = 'html'
    }

    return (isMetaView ?

 {entity.name}

assets extension is currently in beta

      {link ?
Asset is linked to file: {link}
 :
}

        Embed into a template content, template helpers using or a custom script:

            { '{#asset ' + entity.name + '}'}

            { '{#asset ' + entity.name + ' @encoding=utf8|base64|string|link}'}

           Download file

        {entity.link
          ?  : <button className='button confirmation' onClick={() => AssetUploadButton.OpenUpload()}>
          Upload file</button>}
        <button className='button confirmation' onClick={() => this.openEditor()}>
           Open in editor
        </button>

 : <TextEditor
      name={entity._id}
      mode={mode}
      value={atob(((entity.content || entity.forceUpdate) ? entity.content : content) || '')}
      onUpdate={(v) => onUpdate(Object.assign({}, entity, {content: btoa(v), forceUpdate: true}))} />)
  }
}

<commit_msg>fix error handling when changing asset link<commit_after>import React, { Component } from 'react'
import AssetUploadButton from './AssetUploadButton.js'
import Studio, { TextEditor } from 'jsreport-studio'
import superagent from 'superagent'
import Promise from 'bluebird'

// Studio.api currently always open dialogs on failures and that is what we don't want, so arbitrary implementaiton here
const getTextFromApi = (path) => {
  return new Promise((resolve, reject) => {
    const request = superagent.get(Studio.resolveUrl(path))
    request.end((err, { text } = {}) => err ? reject(new Error(text || err.toString())) : resolve(text))
  })
}

export default class FileEditor extends Component {
  constructor () {
    super()
    this.state = { isMetaView: true }
  }

  async openEditor () {
    const { entity } = this.props

    var content = entity.content
    if (entity.link && !entity.content && !this.state.loadFailed) {
      try {
        await Studio.saveEntity(entity._id)
        content = btoa(await Studio.api.get(`assets/${encodeURIComponent(entity.name)}`, { parseJSON: false }))
      } catch (e) {
        this.setState({ loadFailed: true })
        throw e
      }
    }

    this.setState({ isMetaView: false, content: content })
  }

  async componentDidUpdate (prevProps) {
    const { entity } = this.props

    if (entity.link && (!this.state.link || prevProps.entity.link !== entity.link) && !this.state.loadFailed) {
      try {
        const link = await getTextFromApi(`assets/link/${encodeURIComponent(entity.link)}`)
        this.setState({ link: link })
      } catch (e) {
        this.setState({ link: e.message })
      }
    }
  }

  render () {
    const { entity, onUpdate } = this.props
    const { isMetaView, content, link } = this.state
    const downloadUrl = Studio.resolveUrl(`assets/${encodeURIComponent(entity.name)}?download=true`)
    let mode = 'text'
    if (entity.name.includes('.js')) {
      mode = 'javascript'
    }

    if (entity.name.includes('.css')) {
      mode = 'css'
    }

    if (entity.name.includes('.html')) {
      mode = 'html'
    }

    return (isMetaView ?

 {entity.name}

assets extension is currently in beta

      {link ?
Asset is linked to file: {link}
 :
}

        Embed into a template content, template helpers using or a custom script:

            { '{#asset ' + entity.name + '}'}

            { '{#asset ' + entity.name + ' @encoding=utf8|base64|string|link}'}

           Download file

        {entity.link
          ?  : <button className='button confirmation' onClick={() => AssetUploadButton.OpenUpload()}>
          Upload file</button>}
        <button className='button confirmation' onClick={() => this.openEditor()}>
           Open in editor
        </button>

 : <TextEditor
      name={entity._id}
      mode={mode}
      value={atob(((entity.content || entity.forceUpdate) ? entity.content : content) || '')}
      onUpdate={(v) => onUpdate(Object.assign({}, entity, {content: btoa(v), forceUpdate: true}))} />)
  }
}

<|endoftext|>


<commit_before>import Adapter from 'ember-data/adapter';
import Ember from 'ember';
import Soda from 'npm:soda-js';

export default Adapter.extend({
  defaultSerializer: 'socrata',
  findRecord(store, type, id) {
    let adapter = this;
    let consumer = new Soda.Consumer(adapter.get('config.dataRepo'));
    let modelId = `${type.modelName}_id`;
    let data = {};
    data[modelId] = id;
    return new Ember.RSVP.Promise(function(resolve, reject) {
      consumer
        .query()
        .withDataset(adapter.get('dataset'))
        .where(data)
        .limit(1)
        .getRows()
        .on('success', function(data) {
          Ember.run(null, resolve, data);
        })
        .on('error', function(error) {
          Ember.run(null, reject, error);
        });
    });
  },
  findAll() {
    let adapter = this;
    let consumer = new Soda.Consumer(adapter.get('config.dataRepo'));
    return new Ember.RSVP.Promise(function(resolve, reject) {
      consumer
        .query()
        .withDataset(adapter.get('dataset'))
        .getRows()
        .on('success', function(data) {
          Ember.run(null, resolve, data);
        })
        .on('error', function(error) {
          Ember.run(null, reject, error);
        });
    });
  },
  query(store, type, query) {
    let adapter = this;
    let consumer = new Soda.Consumer(adapter.get('config.dataRepo'));
    return new Ember.RSVP.Promise(function(resolve, reject) {
      consumer
        .query()
        .withDataset(adapter.get('dataset'))
        .where(query)
        .getRows()
        .on('success', function(data) {
          Ember.run(null, resolve, data);
        })
        .on('error', function(error) {
          Ember.run(null, reject, error);
        });
    });
  },
});
<commit_msg>Implemented `DS.Adapter.query()` method<commit_after>import Adapter from 'ember-data/adapter';
import Ember from 'ember';
import Soda from 'npm:soda-js';

export default Adapter.extend({
  defaultSerializer: 'socrata',
  findRecord(store, type, id) {
    let adapter = this;
    let consumer = new Soda.Consumer(adapter.get('config.dataRepo'));
    let modelId = `${type.modelName}_id`;
    let data = {};
    data[modelId] = id;
    return new Ember.RSVP.Promise(function(resolve, reject) {
      consumer
        .query()
        .withDataset(adapter.get('dataset'))
        .where(data)
        .limit(1)
        .getRows()
        .on('success', function(data) {
          Ember.run(null, resolve, data);
        })
        .on('error', function(error) {
          Ember.run(null, reject, error);
        });
    });
  },
  findAll() {
    let adapter = this;
    let consumer = new Soda.Consumer(adapter.get('config.dataRepo'));
    return new Ember.RSVP.Promise(function(resolve, reject) {
      consumer
        .query()
        .withDataset(adapter.get('dataset'))
        .getRows()
        .on('success', function(data) {
          Ember.run(null, resolve, data);
        })
        .on('error', function(error) {
          Ember.run(null, reject, error);
        });
    });
  },
  query(store, type, query) {
    let adapter = this;
    let consumer = new Soda.Consumer(adapter.get('config.dataRepo'));
    return new Ember.RSVP.Promise(function(resolve, reject) {
      let queryBuilder = consumer.query().withDataset(adapter.get('dataset'));

      if ('soql' in query || 'query' in query) {
        let soql = query['soql'] || query['query'];
        queryBuilder.query(soql);
      }

      if ('where' in query) {
        let where = query['where'];
        if (where instanceof Array) {
          queryBuilder.where(...where);
        } else {
          queryBuilder.where(where);
        }
      }

      if ('limit' in query) {
        queryBuilder.limit(query['limit']);
      }

      if ('offset' in query) {
        queryBuilder.offset(query['offset']);
      }

      if ('order' in query) {
        queryBuilder.order(...query['order']);
      }

      if ('select' in query) {
        queryBuilder.order(...query['select']);
      }

      if ('q' in query) {
        queryBuilder.q(query['q']);
      }

      queryBuilder
        .getRows()
        .on('success', function(data) {
          Ember.run(null, resolve, data);
        })
        .on('error', function(error) {
          Ember.run(null, reject, error);
        });
    });
  },
});
<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');
var Ractive = require('ractive');
var logger = require('../../src/utils/logger');
var ractiveTypes = require('../../src/template/ractive_types');

/**
 * Ractive does a breaks non-alphanumeric interpolator keys into an object format
 * This reverses the process
 * @param  {Object} template Ractive object to get lookup key from
 * @return {String}          Raw value to lookup from context
 */
module.exports.parseInterpolatorString = function(template) {
  if (!template) {
    return '';
  }
  if (template.x) {
    var str = template.x.s;
    str = str.replace(/_(\d)/g, function(fullMatch, match) {
      return template.x.r[match];
    });
    return str;
  } else {
    return template.r || '';
  }
};

/**
 * Find partials so they can be required
 * @param  {Object} template    Template object to parse over
 * @param  {Object} partials    Partials object to add to
 * @return {Object}             Partials referenced in this template
 */
function _findPartials(template, partials) {
  if (template instanceof Array) {
    // Arrays need mapping over
    for (var i = 0; i < template.length; i++) {
      _findPartials(template[i], partials);
    }
    return;
  }

  switch (template.t) {
    // Partial means we found one
    case ractiveTypes.PARTIAL:
      var partialName = module.exports.parseInterpolatorString(template);
      partials[partialName] = true;
      break;

      // Element or Sections should be iterated into
    case ractiveTypes.ELEMENT:
    case ractiveTypes.SECTION:
      _findPartials(template.f, partials);
      break;
  }
}

module.exports.findPartials = function(template) {
  var partials = {};
  _findPartials(template, partials);
  return _.keys(partials);
};

/**
 * Compiles a template with Ractive
 * Throws exception if template is unable to be parsed
 * @param  {String} contents  Contents of template file
 * @param  {String} srcFile   Path to template file
 * @return {Object}           Rendered template object
 */
module.exports.compileTemplate = function(contents, srcFile) {
  var parsed;
  try {
    parsed = Ractive.parse(contents, {
      stripComments: false,
      preserveWhitespace: true
    });
  } catch (ex) {
    logger.error('Unable to parse ' + (srcFile || contents));
    throw new Error('Compilation error: ' + ex.message);
  }

  return parsed.t;
};

module.exports.handleDynamicComments = function(template) {
  if (typeof template === 'string' || typeof template === 'undefined') {
    // String or undefined means we've bottomed out
    return;
  } else if (template instanceof Array) {
    // Arrays need mapping over
    for (var i = 0; i < template.length; i++) {
      module.exports.handleDynamicComments(template[i]);
    }
    return;
  }

  switch (template.t) {
    // Comment means we found one
    case ractiveTypes.COMMENT:
      var parsed = Ractive.parse(template.c, {
        stripComments: false,
        preserveWhitespace: true
      });
      template.c = parsed.t;
      break;

      // Element or Sections should be iterated into
    case ractiveTypes.ELEMENT:
    case ractiveTypes.SECTION:
      module.exports.handleDynamicComments(template.f);
      break;
  }

  return;
};
<commit_msg>Fix for template compilation issue<commit_after>'use strict';

var _ = require('underscore');
var Ractive = require('ractive');
var logger = require('../../src/utils/logger');
var ractiveTypes = require('../../src/template/ractive_types');

/**
 * Ractive does a breaks non-alphanumeric interpolator keys into an object format
 * This reverses the process
 * @param  {Object} template Ractive object to get lookup key from
 * @return {String}          Raw value to lookup from context
 */
module.exports.parseInterpolatorString = function(template) {
  if (!template) {
    return '';
  }
  if (template.x) {
    var str = template.x.s;
    str = str.replace(/_(\d)/g, function(fullMatch, match) {
      return template.x.r[match];
    });
    return str;
  } else {
    return template.r || '';
  }
};

/**
 * Find partials so they can be required
 * @param  {Object} template    Template object to parse over
 * @param  {Object} partials    Partials object to add to
 * @return {Object}             Partials referenced in this template
 */
function _findPartials(template, partials) {
  if (typeof template === 'string' || typeof template === 'undefined') {
    // String or undefined means we've bottomed out
    return;
  } else if (template instanceof Array || template == null) {
    // Arrays need mapping over
    for (var i = 0; i < template.length; i++) {
      _findPartials(template[i], partials);
    }
    return;
  }

  switch (template.t) {
    // Partial means we found one
    case ractiveTypes.PARTIAL:
      var partialName = module.exports.parseInterpolatorString(template);
      partials[partialName] = true;
      break;

      // Element or Sections should be iterated into
    case ractiveTypes.ELEMENT:
    case ractiveTypes.SECTION:
      _findPartials(template.f, partials);
      break;
  }
}

module.exports.findPartials = function(template) {
  var partials = {};
  _findPartials(template, partials);
  return _.keys(partials);
};

/**
 * Compiles a template with Ractive
 * Throws exception if template is unable to be parsed
 * @param  {String} contents  Contents of template file
 * @param  {String} srcFile   Path to template file
 * @return {Object}           Rendered template object
 */
module.exports.compileTemplate = function(contents, srcFile) {
  var parsed;
  try {
    parsed = Ractive.parse(contents, {
      stripComments: false,
      preserveWhitespace: true
    });
  } catch (ex) {
    logger.error('Unable to parse ' + (srcFile || contents));
    throw new Error('Compilation error: ' + ex.message);
  }

  return parsed.t;
};

module.exports.handleDynamicComments = function(template) {
  if (typeof template === 'string' || typeof template === 'undefined') {
    // String or undefined means we've bottomed out
    return;
  } else if (template instanceof Array) {
    // Arrays need mapping over
    for (var i = 0; i < template.length; i++) {
      module.exports.handleDynamicComments(template[i]);
    }
    return;
  }

  switch (template.t) {
    // Comment means we found one
    case ractiveTypes.COMMENT:
      var parsed = Ractive.parse(template.c, {
        stripComments: false,
        preserveWhitespace: true
      });
      template.c = parsed.t;
      break;

      // Element or Sections should be iterated into
    case ractiveTypes.ELEMENT:
    case ractiveTypes.SECTION:
      module.exports.handleDynamicComments(template.f);
      break;
  }

  return;
};
<|endoftext|>


<commit_before>/* eslint-disable no-param-reassign, prefer-template, no-void, consistent-return */

import AccessorUtilities from './lib/utils/accessor';

export default class Autosave {
  constructor(field, key) {
    this.field = field;

    this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe();
    if (key.join != null) {
      key = key.join('/');
    }
    this.key = 'autosave/' + key;
    this.field.data('autosave', this);
    this.restore();
    this.field.on('input', () => this.save());
  }

  restore() {
    if (!this.isLocalStorageAvailable) return;
    if (!this.field.length) return;

    const text = window.localStorage.getItem(this.key);

    if ((text != null ? text.length : void 0) > 0) {
      this.field.val(text);
    }

    this.field.trigger('input');
    // v-model does not update with jQuery trigger
    // https://github.com/vuejs/vue/issues/2804#issuecomment-216968137
    const event = new Event('change', { bubbles: true, cancelable: false });
    const field = this.field.get(0);
    if (field) {
      field.dispatchEvent(event);
    }
  }

  save() {
    if (!this.field.length) return;

    const text = this.field.val();

    if (this.isLocalStorageAvailable && (text != null ? text.length : void 0) > 0) {
      return window.localStorage.setItem(this.key, text);
    }

    return this.reset();
  }

  reset() {
    if (!this.isLocalStorageAvailable) return;

    return window.localStorage.removeItem(this.key);
  }
}
<commit_msg>Add dispose method to autosave mixin.<commit_after>/* eslint-disable no-param-reassign, prefer-template, no-void, consistent-return */

import AccessorUtilities from './lib/utils/accessor';

export default class Autosave {
  constructor(field, key) {
    this.field = field;

    this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe();
    if (key.join != null) {
      key = key.join('/');
    }
    this.key = 'autosave/' + key;
    this.field.data('autosave', this);
    this.restore();
    this.field.on('input', () => this.save());
  }

  restore() {
    if (!this.isLocalStorageAvailable) return;
    if (!this.field.length) return;

    const text = window.localStorage.getItem(this.key);

    if ((text != null ? text.length : void 0) > 0) {
      this.field.val(text);
    }

    this.field.trigger('input');
    // v-model does not update with jQuery trigger
    // https://github.com/vuejs/vue/issues/2804#issuecomment-216968137
    const event = new Event('change', { bubbles: true, cancelable: false });
    const field = this.field.get(0);
    if (field) {
      field.dispatchEvent(event);
    }
  }

  save() {
    if (!this.field.length) return;

    const text = this.field.val();

    if (this.isLocalStorageAvailable && (text != null ? text.length : void 0) > 0) {
      return window.localStorage.setItem(this.key, text);
    }

    return this.reset();
  }

  reset() {
    if (!this.isLocalStorageAvailable) return;

    return window.localStorage.removeItem(this.key);
  }

  dispose() {
    this.field.off('input');
  }
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from '../templates/sl-behavior';

/**
 * Adds ability to hide template content of a component under a given set of conditions
 *
 * @module
 * @augments ember/Mixin
 */
export default Ember.Mixin.create({

    // -------------------------------------------------------------------------
    // Dependencies

    /**
     * The behavior service used to check if a supplied behavior is allowed
     *
     * @type {ember/Service}
     */
    behaviorService: Ember.inject.service( 'sl-behavior' ),

    // -------------------------------------------------------------------------
    // Attributes

    /** @type {Object} */
    layout,

    /** @type {String} */
    tagName: 'span',

    // -------------------------------------------------------------------------
    // Actions

    // -------------------------------------------------------------------------
    // Events

    // -------------------------------------------------------------------------
    // Properties

    /**
     * Indicates whether an activity is allowed if the behaviors set on the service allow it
     *
     * When set to a function, the return value must be a Boolean and will not
     * be observed by the showContent() method.
     *
     * @type {Boolean|Function}
     */
    possible: true,

    // -------------------------------------------------------------------------
    // Observers

    // -------------------------------------------------------------------------
    // Methods

    /**
     * Implement this function to customize the block content's viewability
     *
     * @function
     * @abstract
     * @param {String} activity
     * @param {String} resource
     * @param {Boolean} possible
     * @throws {ember.assert} If this function has not been implemented on the derived class
     * @returns {Boolean} true if the content is viewable, otherwise false
     */
    isViewable( activity, resource, possible ) {
        /* jshint unused:false */

        Ember.assert(
            'The mixins/component.isViewable() method should be implemented on the derived class'
        );

        return false;
    },
    /* jshint unused:true */

    /**
     * Determines whether or not to show the content in the template
     *
     * @function
     * @throws {ember.assert} If the `possible` property is not a Boolean
     * @returns {Boolean}
     */
    showContent: Ember.computed(
        'behaviorService.behaviors',
        'possible',
        function() {
            const possible = this.get( 'possible' );

            Ember.assert(
                'Expects `possible` property to be a Boolean',
                'boolean' === Ember.typeOf( possible )
            );

            return this.isViewable(
                this.get( 'activity' ),
                this.get( 'resource' ),
                possible
            );
        }
    )
});
<commit_msg>Reference all listed parameters in return statement to satisfy linting requirements; cast return value as Boolean to satisfy test requirements.<commit_after>import Ember from 'ember';
import layout from '../templates/sl-behavior';

/**
 * Adds ability to hide template content of a component under a given set of conditions
 *
 * @module
 * @augments ember/Mixin
 */
export default Ember.Mixin.create({

    // -------------------------------------------------------------------------
    // Dependencies

    /**
     * The behavior service used to check if a supplied behavior is allowed
     *
     * @type {ember/Service}
     */
    behaviorService: Ember.inject.service( 'sl-behavior' ),

    // -------------------------------------------------------------------------
    // Attributes

    /** @type {Object} */
    layout,

    /** @type {String} */
    tagName: 'span',

    // -------------------------------------------------------------------------
    // Actions

    // -------------------------------------------------------------------------
    // Events

    // -------------------------------------------------------------------------
    // Properties

    /**
     * Indicates whether an activity is allowed if the behaviors set on the service allow it
     *
     * When set to a function, the return value must be a Boolean and will not
     * be observed by the showContent() method.
     *
     * @type {Boolean|Function}
     */
    possible: true,

    // -------------------------------------------------------------------------
    // Observers

    // -------------------------------------------------------------------------
    // Methods

    /**
     * Implement this function to customize the block content's viewability
     *
     * @function
     * @abstract
     * @param {String} activity
     * @param {String} resource
     * @param {Boolean} possible
     * @throws {ember.assert} If this function has not been implemented on the derived class
     * @returns {Boolean} true if the content is viewable, otherwise false
     */
    isViewable( activity, resource, possible ) {
        Ember.assert(
            'The mixins/component.isViewable() method should be implemented on the derived class'
        );

        return Boolean( activity && resource && possible && false );
    },

    /**
     * Determines whether or not to show the content in the template
     *
     * @function
     * @throws {ember.assert} If the `possible` property is not a Boolean
     * @returns {Boolean}
     */
    showContent: Ember.computed(
        'behaviorService.behaviors',
        'possible',
        function() {
            const possible = this.get( 'possible' );

            Ember.assert(
                'Expects `possible` property to be a Boolean',
                'boolean' === Ember.typeOf( possible )
            );

            return this.isViewable(
                this.get( 'activity' ),
                this.get( 'resource' ),
                possible
            );
        }
    )
});
<|endoftext|>


<commit_before>/*
 Copyright 2018 Carmilla Mina Jankovic

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

const elementCreator = require('../../ElementCreator');
const accessCentral = require('../../AccessCentral');
const storageManager = require('../../StorageManager');

const cssClasses = {
  focusElement: 'focusElement',
  markElement: 'markElement',
  newElement: 'newElement',
  removeElement: 'removeElement',
};

class BaseView {
  constructor({
    classes,
    minimumAccessLevel,
    elementId = `elem-${Date.now()}`,
  }) {
    this.itemChangeTimeout = 800;
    this.minimumAccessLevel = minimumAccessLevel;
    this.classes = classes;
    this.elementId = elementId;
    this.element = elementCreator.createContainer({
      classes,
      elementId,
    });

    if (minimumAccessLevel) {
      accessCentral.addAccessElement({
        element: this.element,
        minimumAccessLevel: this.minimumAccessLevel,
      });
    }
  }

  replaceOnParent({ element }) {
    const parentElement = this.getParentElement();

    if (parentElement) {
      parentElement.replaceChild(element, this.getThisElement());
    }

    this.element = element;
  }

  addToView({
    element,
    insertBeforeElement,
    shouldPrepend,
  }) {
    if (insertBeforeElement) {
      element.insertBefore(this.element, insertBeforeElement);
    } else if (shouldPrepend) {
      element.insertBefore(this.element, element.firstElementChild);
    } else {
      element.appendChild(this.element);
    }
  }

  getThisElement() {
    return document.getElementById(this.elementId);
  }

  getParentElement() {
    const thisElement = this.getThisElement();

    if (thisElement) {
      return this.getThisElement().parentNode;
    }

    return undefined;
  }

  removeFromView() {
    this.getParentElement().removeChild(this.getThisElement());
  }

  showView() {
    console.log('access show', this.minimumAccessLevel, this.element);

    if (this.minimumAccessLevel && this.minimumAccessLevel > storageManager.getAccessLevel()) {
      return;
    }

    this.element.classList.remove('hide');
  }

  hideView() {
    this.element.classList.add('hide');
  }

  toggleView() {
    if (this.minimumAccessLevel && this.minimumAccessLevel > storageManager.getAccessLevel()) {
      return;
    }

    this.element.classList.toggle('hide');
  }

  getElement(elementId) {
    return document.getElementById(`${this.elementId}${elementId}`);
  }

  getElementId() {
    return this.elementId;
  }

  static hasAccess({ object, user }) {
    return accessCentral.hasAccessTo({
      objectToAccess: object,
      toAuth: user,
    });
  }

  static findClosestElementId({
    paramName,
    fallbackParamName,
    objects,
    reverse,
    targetVar,
  }) {
    const isNumber = typeof paramName === 'number';
    const closest = isNumber
      ? objects.reduce((previous, current) => {
        const prevVar = previous[paramName] || previous[fallbackParamName];
        const currVar = current[paramName] || current[fallbackParamName];

        if (reverse) {
          return (Math.abs(currVar - targetVar) < Math.abs(prevVar - targetVar))
            ? previous
            : current;
        }

        return (Math.abs(currVar - targetVar) < Math.abs(prevVar - targetVar))
          ? current
          : previous;
      })
      : objects.find((closeObject, index) => {
        if (index >= (objects.length - 1)) {
          return true;
        }

        const closeVar = objects[index][paramName] || objects[index][fallbackParamName];

        if (reverse) {
          return closeVar < targetVar;
        }

        return closeVar > targetVar;
      });

    return closest.objectId;
  }

  removeElement({
    object,
    parentElement,
    shouldAnimate = false,
  }) {
    const { objectId } = object;
    const toRemove = this.getElement(objectId);
    const removeFrom = parentElement || this.element;

    if (shouldAnimate) {
      toRemove.classList.add(cssClasses.removeElement);

      setTimeout(() => {
        const element = this.getElement(objectId);

        if (element) {
          removeFrom.removeChild(element);
        }
      }, this.itemChangeTimeout / 4);

      return;
    }

    removeFrom.removeChild(toRemove);
  }

  animateElement({
    elementId,
    element,
  }) {
    const elementToAnimate = element || this.getElement(elementId);

    if (elementToAnimate) {
      elementToAnimate.classList.add(cssClasses.newElement);
      setTimeout(() => { elementToAnimate.classList.remove(cssClasses.newElement); }, this.itemChangeTimeout);
    }
  }
}

module.exports = BaseView;
<commit_msg>Improved code for removal of elements in list<commit_after>/*
 Copyright 2018 Carmilla Mina Jankovic

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

const elementCreator = require('../../ElementCreator');
const accessCentral = require('../../AccessCentral');
const storageManager = require('../../StorageManager');

const cssClasses = {
  focusElement: 'focusElement',
  markElement: 'markElement',
  newElement: 'newElement',
  removeElement: 'removeElement',
};

class BaseView {
  constructor({
    classes,
    minimumAccessLevel,
    elementId = `elem-${Date.now()}`,
  }) {
    this.itemChangeTimeout = 800;
    this.minimumAccessLevel = minimumAccessLevel;
    this.classes = classes;
    this.elementId = elementId;
    this.element = elementCreator.createContainer({
      classes,
      elementId,
    });

    if (minimumAccessLevel) {
      accessCentral.addAccessElement({
        element: this.element,
        minimumAccessLevel: this.minimumAccessLevel,
      });
    }
  }

  replaceOnParent({ element }) {
    const parentElement = this.getParentElement();

    if (parentElement) {
      parentElement.replaceChild(element, this.getThisElement());
    }

    this.element = element;
  }

  addToView({
    element,
    insertBeforeElement,
    shouldPrepend,
  }) {
    if (insertBeforeElement) {
      element.insertBefore(this.element, insertBeforeElement);
    } else if (shouldPrepend) {
      element.insertBefore(this.element, element.firstElementChild);
    } else {
      element.appendChild(this.element);
    }
  }

  getThisElement() {
    return document.getElementById(this.elementId);
  }

  getParentElement() {
    const thisElement = this.getThisElement();

    if (thisElement) {
      return this.getThisElement().parentNode;
    }

    return undefined;
  }

  removeFromView() {
    this.getParentElement().removeChild(this.getThisElement());
  }

  showView() {
    console.log('access show', this.minimumAccessLevel, this.element);

    if (this.minimumAccessLevel && this.minimumAccessLevel > storageManager.getAccessLevel()) {
      return;
    }

    this.element.classList.remove('hide');
  }

  hideView() {
    this.element.classList.add('hide');
  }

  toggleView() {
    if (this.minimumAccessLevel && this.minimumAccessLevel > storageManager.getAccessLevel()) {
      return;
    }

    this.element.classList.toggle('hide');
  }

  getElement(elementId) {
    return document.getElementById(`${this.elementId}${elementId}`);
  }

  getElementId() {
    return this.elementId;
  }

  static hasAccess({ object, user }) {
    return accessCentral.hasAccessTo({
      objectToAccess: object,
      toAuth: user,
    });
  }

  static findClosestElementId({
    paramName,
    fallbackParamName,
    objects,
    reverse,
    targetVar,
  }) {
    const isNumber = typeof paramName === 'number';
    const closest = isNumber
      ? objects.reduce((previous, current) => {
        const prevVar = previous[paramName] || previous[fallbackParamName];
        const currVar = current[paramName] || current[fallbackParamName];

        if (reverse) {
          return (Math.abs(currVar - targetVar) < Math.abs(prevVar - targetVar))
            ? previous
            : current;
        }

        return (Math.abs(currVar - targetVar) < Math.abs(prevVar - targetVar))
          ? current
          : previous;
      })
      : objects.find((closeObject, index) => {
        if (index >= (objects.length - 1)) {
          return true;
        }

        const closeVar = objects[index][paramName] || objects[index][fallbackParamName];

        if (reverse) {
          return closeVar < targetVar;
        }

        return closeVar > targetVar;
      });

    return closest.objectId;
  }

  removeElement({
    object,
    shouldAnimate = false,
  }) {
    const { objectId } = object;
    const toRemove = this.getElement(objectId);

    if (shouldAnimate) {
      toRemove.classList.add(cssClasses.removeElement);

      setTimeout(() => {
        const element = this.getElement(objectId);

        if (element) {
          toRemove.parentElement.removeChild(element);
        }
      }, this.itemChangeTimeout / 4);

      return;
    }

    toRemove.parentElement.removeChild(toRemove);
  }

  animateElement({
    elementId,
    element,
  }) {
    const elementToAnimate = element || this.getElement(elementId);

    if (elementToAnimate) {
      elementToAnimate.classList.add(cssClasses.newElement);
      setTimeout(() => { elementToAnimate.classList.remove(cssClasses.newElement); }, this.itemChangeTimeout);
    }
  }
}

module.exports = BaseView;
<|endoftext|>