<commit_before>class App extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {
      loading:true,
      hpVersion:window.hpVersion
    };
    this.initHomePage = this.initHomePage.bind(this);
    this.updateDimensions = this.updateDimensions.bind(this);
    this.convertDataObject = this.convertDataObject.bind(this);
  }

  componentWillMount() {
    this.updateDimensions();
  }

  componentWillUnmount(){
    window.removeEventListener("resize", this.updateDimensions);
    window.removeEventListener("orientationchange",this.updateDimensions);
  }

  componentDidMount() {
    this.initHomePage();
  }

  initHomePage(){

    window.addEventListener("resize", this.updateDimensions);
    window.addEventListener("orientationchange",this.updateDimensions);

    let env = "live";
    if (location.hostname.endsWith('cc')) {
      env = "test";
    } else if (location.hostname.endsWith('localhost')) {
      env = "test";
    }

    this.setState({env:env},function(){
      this.convertDataObject();
    });

  }

  updateDimensions(){

    const width = window.innerWidth;
    let device;
    if (width >= 910){
      device = "large";
    } else if (width < 910 && width >= 610){
      device = "mid";
    } else if (width < 610){
      device = "tablet";
    }

    this.setState({device:device});

  }

  convertDataObject() {
    let productGroupsArray = [];
    for (var i in window.data) {
      if (i !== "comments" && i !== "featureProducts"){
        const productGroup = {
          title:window.data[i].title,
          catIds:window.data[i].catIds,
          products:JSON.parse(window.data[i].products)
        }
        productGroupsArray.push(productGroup);
      }
    }
    this.setState({productGroupsArray:productGroupsArray,loading:false});
  }

  render(){
    let productCarouselsContainer;
    if (this.state.loading === false){
      productCarouselsContainer = this.state.productGroupsArray.map((pgc,index) => (

              <ProductCarousel
                products={pgc.products}
                device={this.state.device}
                title={pgc.title}
                catIds={pgc.catIds}
                link={'/'}
                env={this.state.env}
              />

      ));
    }

    const featuredProduct = JSON.parse(window.data['featureProducts']);

    return (

        <SpotlightProduct
          env={this.state.env}
          featuredProduct={featuredProduct}
        />
        {productCarouselsContainer}

    )
  }
}

class SpotlightProduct extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {
      featuredProduct:this.props.featuredProduct
    };
    this.onSpotlightMenuClick = this.onSpotlightMenuClick.bind(this);
  }

  onSpotlightMenuClick(val){
    let url = "/home/showfeaturejson/page/";
    if (val === "random"){ url += "0"; }
    else { url += "1"; }
    const self = this;
    $.ajax({url: url,cache: false}).done(function(response){
        self.setState({featuredProduct:response});
    });
  }

  render(){

    let imageBaseUrl;
    if (this.props.env === 'live') {
      imageBaseUrl = 'cn.opendesktop.org';
    } else {
      imageBaseUrl = 'cn.opendesktop.cc';
    }

    let description = this.state.featuredProduct.description;
    if (description && description.length > 295){
      description = this.state.featuredProduct.description.substring(0,295) + "...";
    }

    let featuredLabelDisplay;
    if (this.state.featuredProduct.feature === "1"){
      featuredLabelDisplay = "featured"
    }

    return(

In the Spotlight

              {featuredLabelDisplay}

{this.state.featuredProduct.title}

{this.state.featuredProduct.category}

                  {this.state.featuredProduct.username}

                    score {this.state.featuredProduct.laplace_score + "%"}

                {description}

               this.onSpotlightMenuClick('random')}>random
               this.onSpotlightMenuClick('featured')}>featured

    );
  }
}

class ProductCarousel extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {
      products:this.props.products,
      offset:5,
      disableleftArrow:true
    };
    this.updateDimensions = this.updateDimensions.bind(this);
    this.animateProductCarousel = this.animateProductCarousel.bind(this);
    this.getNextProductsBatch = this.getNextProductsBatch.bind(this);
  }

  componentWillMount() {
    window.addEventListener("resize", this.updateDimensions);
  }

  componentDidMount() {
    this.updateDimensions();
  }

  updateDimensions(animateCarousel){

    /*let itemsPerRow;
    if (this.props.device === 'large'){
      itemsPerRow = 5;
    } else if (this.props.device === 'mid'){
      itemsPerRow = 4;
    } else if (this.props.device === 'tablet'){
      itemsPerRow = 3;
    }*/

    let itemsPerRow = 5;
    if (window.hpVersion === 2){
      itemsPerRow = 6;
    }

    const containerWidth = $('#main-content').width();
    const containerNumber = Math.ceil(this.state.products.length / itemsPerRow);
    const sliderWidth = containerWidth * containerNumber;
    const itemWidth = containerWidth / itemsPerRow;
    let sliderPosition = 0;
    if (this.state.sliderPosition){
      sliderPosition = this.state.sliderPosition;
    }
    this.setState({
      sliderPosition:sliderPosition,
      containerWidth:containerWidth,
      sliderWidth:sliderWidth,
      itemWidth:itemWidth
    },function(){
      if (animateCarousel){
        this.animateProductCarousel('right',animateCarousel);
      }
    });
  }

  animateProductCarousel(dir,animateCarousel){

    let newSliderPosition = this.state.sliderPosition;
    const endPoint = this.state.sliderWidth - this.state.containerWidth;

    if (dir === 'left'){
      if (this.state.sliderPosition > 0){
        newSliderPosition = this.state.sliderPosition - this.state.containerWidth;
      }
    } else {
      if (this.state.sliderPosition < endPoint){
        newSliderPosition = this.state.sliderPosition + this.state.containerWidth;
      } else {
        if (!animateCarousel){
          this.getNextProductsBatch();
        }
      }
    }

    this.setState({sliderPosition:newSliderPosition},function(){

      let disableleftArrow = false;
      if (this.state.sliderPosition <= 0){
        disableleftArrow = true;
      }

      let disableRightArrow = false;
      if (this.state.sliderPosition >= endPoint && this.state.finishedProducts === true){
        disableRightArrow = true;
      }

      this.setState({disableRightArrow:disableRightArrow,disableleftArrow:disableleftArrow});

    });
  }

  getNextProductsBatch(){
    let url = "/home/showlastproductsjson/?page=1&limit=5&offset="+this.state.offset+"&catIDs="+this.props.catIds+"&isoriginal=0";
    const self = this;
    $.ajax({url: url,cache: false}).done(function(response){
        const products = self.state.products.concat(response);
        const offset = self.state.offset + 5;
        let finishedProducts = false;
        if (response.length < 5){
          finishedProducts = true;
        }
        self.setState({products:products,offset:offset,finishedProducts:finishedProducts},function(){
          const animateCarousel = true;
          self.updateDimensions(animateCarousel);
        });
    });
  }

  render(){
    let carouselItemsDisplay;
    if (this.state.products && this.state.products.length > 0){
      carouselItemsDisplay = this.state.products.map((product,index) => (
        <ProductCarouselItem
          key={index}
          product={product}
          itemWidth={this.state.itemWidth}
          env={this.props.env}
        />
      ));
    }

    let carouselArrowLeftDisplay;
    if (this.state.disableleftArrow){
      carouselArrowLeftDisplay = (

      )
    } else {
      carouselArrowLeftDisplay = (
         this.animateProductCarousel('left')} className="carousel-arrow arrow-left">

      );
    }

    let carouselArrowRightDisplay;
    if (this.state.disableRightArrow){
      carouselArrowRightDisplay = (

      )
    } else {
      carouselArrowRightDisplay = (
         this.animateProductCarousel('right')} className="carousel-arrow arrow-right">

      );
    }

    let hpVersionClass = "one";
    let carouselWrapperStyling = {};
    let carouselArrowsMargin;
    if (window.hpVersion === 2){
      hpVersionClass = "two";
      carouselWrapperStyling = {
        "paddingLeft":this.state.itemWidth / 2,
        "paddingRight":this.state.itemWidth / 2,
        "height":this.state.itemWidth * 1.35
      }
      carouselArrowsMargin = this.state.itemWidth / 4;
    }

    return (

{this.props.title}

            {carouselArrowLeftDisplay}

              {carouselItemsDisplay}

            {carouselArrowRightDisplay}

    )
  }
}

class ProductCarouselItem extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {};
  }

  render(){
    let imageUrl = this.props.product.image_small;
    if (imageUrl && this.props.product.image_small.indexOf('https://') === -1 && this.props.product.image_small.indexOf('http://') === -1){
      let imageBaseUrl;
      if (this.props.env === 'live') {
        imageBaseUrl = 'cn.opendesktop.org';
      } else {
        imageBaseUrl = 'cn.opendesktop.cc';
      }
      imageUrl = 'https://' + imageBaseUrl + '/cache/200x171/img/' + this.props.product.image_small;
    }

    let paddingTop;
    let productInfoDisplay = (

        {this.props.product.title}
        {this.props.product.username}

    );

    if (window.hpVersion === 2){
      paddingTop = ((this.props.itemWidth * 1.35) / 2) - 10;
      const createDate = new Date(this.props.product.created_at);
      const createdDate = createDate.split(' ')[1] + " " + createDate.split(' ')[2] + " " createDate.split(' ')[3];
      console.log(createdDate);
      let commentsCountDisplay;
      if (this.props.product.comment_count > 0){
        commentsCountDisplay = (
          {this.props.product.count_comments} comments
        )
      }
      productInfoDisplay = (

          {this.props.product.title}
          {this.props.product.cat_title}
          {this.props.product.created_at}
          {commentsCountDisplay}

              score {this.props.product.laplace_score + "%"}

      );
    }

    return (

            {productInfoDisplay}

    )
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('main-content')
);
<commit_msg>no message<commit_after>class App extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {
      loading:true,
      hpVersion:window.hpVersion
    };
    this.initHomePage = this.initHomePage.bind(this);
    this.updateDimensions = this.updateDimensions.bind(this);
    this.convertDataObject = this.convertDataObject.bind(this);
  }

  componentWillMount() {
    this.updateDimensions();
  }

  componentWillUnmount(){
    window.removeEventListener("resize", this.updateDimensions);
    window.removeEventListener("orientationchange",this.updateDimensions);
  }

  componentDidMount() {
    this.initHomePage();
  }

  initHomePage(){

    window.addEventListener("resize", this.updateDimensions);
    window.addEventListener("orientationchange",this.updateDimensions);

    let env = "live";
    if (location.hostname.endsWith('cc')) {
      env = "test";
    } else if (location.hostname.endsWith('localhost')) {
      env = "test";
    }

    this.setState({env:env},function(){
      this.convertDataObject();
    });

  }

  updateDimensions(){

    const width = window.innerWidth;
    let device;
    if (width >= 910){
      device = "large";
    } else if (width < 910 && width >= 610){
      device = "mid";
    } else if (width < 610){
      device = "tablet";
    }

    this.setState({device:device});

  }

  convertDataObject() {
    let productGroupsArray = [];
    for (var i in window.data) {
      if (i !== "comments" && i !== "featureProducts"){
        const productGroup = {
          title:window.data[i].title,
          catIds:window.data[i].catIds,
          products:JSON.parse(window.data[i].products)
        }
        productGroupsArray.push(productGroup);
      }
    }
    this.setState({productGroupsArray:productGroupsArray,loading:false});
  }

  render(){
    let productCarouselsContainer;
    if (this.state.loading === false){
      productCarouselsContainer = this.state.productGroupsArray.map((pgc,index) => (

              <ProductCarousel
                products={pgc.products}
                device={this.state.device}
                title={pgc.title}
                catIds={pgc.catIds}
                link={'/'}
                env={this.state.env}
              />

      ));
    }

    const featuredProduct = JSON.parse(window.data['featureProducts']);

    return (

        <SpotlightProduct
          env={this.state.env}
          featuredProduct={featuredProduct}
        />
        {productCarouselsContainer}

    )
  }
}

class SpotlightProduct extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {
      featuredProduct:this.props.featuredProduct
    };
    this.onSpotlightMenuClick = this.onSpotlightMenuClick.bind(this);
  }

  onSpotlightMenuClick(val){
    let url = "/home/showfeaturejson/page/";
    if (val === "random"){ url += "0"; }
    else { url += "1"; }
    const self = this;
    $.ajax({url: url,cache: false}).done(function(response){
        self.setState({featuredProduct:response});
    });
  }

  render(){

    let imageBaseUrl;
    if (this.props.env === 'live') {
      imageBaseUrl = 'cn.opendesktop.org';
    } else {
      imageBaseUrl = 'cn.opendesktop.cc';
    }

    let description = this.state.featuredProduct.description;
    if (description && description.length > 295){
      description = this.state.featuredProduct.description.substring(0,295) + "...";
    }

    let featuredLabelDisplay;
    if (this.state.featuredProduct.feature === "1"){
      featuredLabelDisplay = "featured"
    }

    return(

In the Spotlight

              {featuredLabelDisplay}

{this.state.featuredProduct.title}

{this.state.featuredProduct.category}

                  {this.state.featuredProduct.username}

                {this.state.featuredProduct.comment_count} comments

                    score {this.state.featuredProduct.laplace_score + "%"}

                {description}

               this.onSpotlightMenuClick('random')}>random
               this.onSpotlightMenuClick('featured')}>featured

    );
  }
}

class ProductCarousel extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {
      products:this.props.products,
      offset:5,
      disableleftArrow:true
    };
    this.updateDimensions = this.updateDimensions.bind(this);
    this.animateProductCarousel = this.animateProductCarousel.bind(this);
    this.getNextProductsBatch = this.getNextProductsBatch.bind(this);
  }

  componentWillMount() {
    window.addEventListener("resize", this.updateDimensions);
  }

  componentDidMount() {
    this.updateDimensions();
  }

  updateDimensions(animateCarousel){

    /*let itemsPerRow;
    if (this.props.device === 'large'){
      itemsPerRow = 5;
    } else if (this.props.device === 'mid'){
      itemsPerRow = 4;
    } else if (this.props.device === 'tablet'){
      itemsPerRow = 3;
    }*/

    let itemsPerRow = 5;
    if (window.hpVersion === 2){
      itemsPerRow = 6;
    }

    const containerWidth = $('#main-content').width();
    const containerNumber = Math.ceil(this.state.products.length / itemsPerRow);
    const sliderWidth = containerWidth * containerNumber;
    const itemWidth = containerWidth / itemsPerRow;
    let sliderPosition = 0;
    if (this.state.sliderPosition){
      sliderPosition = this.state.sliderPosition;
    }
    this.setState({
      sliderPosition:sliderPosition,
      containerWidth:containerWidth,
      sliderWidth:sliderWidth,
      itemWidth:itemWidth
    },function(){
      if (animateCarousel){
        this.animateProductCarousel('right',animateCarousel);
      }
    });
  }

  animateProductCarousel(dir,animateCarousel){

    let newSliderPosition = this.state.sliderPosition;
    const endPoint = this.state.sliderWidth - this.state.containerWidth;

    if (dir === 'left'){
      if (this.state.sliderPosition > 0){
        newSliderPosition = this.state.sliderPosition - this.state.containerWidth;
      }
    } else {
      if (this.state.sliderPosition < endPoint){
        newSliderPosition = this.state.sliderPosition + this.state.containerWidth;
      } else {
        if (!animateCarousel){
          this.getNextProductsBatch();
        }
      }
    }

    this.setState({sliderPosition:newSliderPosition},function(){

      let disableleftArrow = false;
      if (this.state.sliderPosition <= 0){
        disableleftArrow = true;
      }

      let disableRightArrow = false;
      if (this.state.sliderPosition >= endPoint && this.state.finishedProducts === true){
        disableRightArrow = true;
      }

      this.setState({disableRightArrow:disableRightArrow,disableleftArrow:disableleftArrow});

    });
  }

  getNextProductsBatch(){
    let url = "/home/showlastproductsjson/?page=1&limit=5&offset="+this.state.offset+"&catIDs="+this.props.catIds+"&isoriginal=0";
    const self = this;
    $.ajax({url: url,cache: false}).done(function(response){
        const products = self.state.products.concat(response);
        const offset = self.state.offset + 5;
        let finishedProducts = false;
        if (response.length < 5){
          finishedProducts = true;
        }
        self.setState({products:products,offset:offset,finishedProducts:finishedProducts},function(){
          const animateCarousel = true;
          self.updateDimensions(animateCarousel);
        });
    });
  }

  render(){
    let carouselItemsDisplay;
    if (this.state.products && this.state.products.length > 0){
      carouselItemsDisplay = this.state.products.map((product,index) => (
        <ProductCarouselItem
          key={index}
          product={product}
          itemWidth={this.state.itemWidth}
          env={this.props.env}
        />
      ));
    }

    let carouselArrowLeftDisplay;
    if (this.state.disableleftArrow){
      carouselArrowLeftDisplay = (

      )
    } else {
      carouselArrowLeftDisplay = (
         this.animateProductCarousel('left')} className="carousel-arrow arrow-left">

      );
    }

    let carouselArrowRightDisplay;
    if (this.state.disableRightArrow){
      carouselArrowRightDisplay = (

      )
    } else {
      carouselArrowRightDisplay = (
         this.animateProductCarousel('right')} className="carousel-arrow arrow-right">

      );
    }

    let hpVersionClass = "one";
    let carouselWrapperStyling = {};
    let carouselArrowsMargin;
    if (window.hpVersion === 2){
      hpVersionClass = "two";
      carouselWrapperStyling = {
        "paddingLeft":this.state.itemWidth / 2,
        "paddingRight":this.state.itemWidth / 2,
        "height":this.state.itemWidth * 1.35
      }
      carouselArrowsMargin = this.state.itemWidth / 4;
    }

    return (

{this.props.title}

            {carouselArrowLeftDisplay}

              {carouselItemsDisplay}

            {carouselArrowRightDisplay}

    )
  }
}

class ProductCarouselItem extends React.Component {
  constructor(props){
  	super(props);
  	this.state = {};
  }

  render(){
    let imageUrl = this.props.product.image_small;
    if (imageUrl && this.props.product.image_small.indexOf('https://') === -1 && this.props.product.image_small.indexOf('http://') === -1){
      let imageBaseUrl;
      if (this.props.env === 'live') {
        imageBaseUrl = 'cn.opendesktop.org';
      } else {
        imageBaseUrl = 'cn.opendesktop.cc';
      }
      imageUrl = 'https://' + imageBaseUrl + '/cache/200x171/img/' + this.props.product.image_small;
    }

    let paddingTop;
    let productInfoDisplay = (

        {this.props.product.title}
        {this.props.product.username}

    );

    if (window.hpVersion === 2){
      paddingTop = ((this.props.itemWidth * 1.35) / 2) - 10;
      const createDate = new Date(this.props.product.created_at);
      const createdDate = createDate.split(' ')[1] + " " + createDate.split(' ')[2] + " " createDate.split(' ')[3];
      console.log(createdDate);
      let commentsCountDisplay;
      if (this.props.product.comment_count > 0){
        commentsCountDisplay = (
          {this.props.product.count_comments} comments
        )
      }
      productInfoDisplay = (

          {this.props.product.title}
          {this.props.product.cat_title}
          {this.props.product.created_at}
          {commentsCountDisplay}

              score {this.props.product.laplace_score + "%"}

      );
    }

    return (

            {productInfoDisplay}

    )
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('main-content')
);
<|endoftext|>


<commit_before>/* This file is part of Indico.
 * Copyright (C) 2002 - 2016 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

(function($) {
    $.widget("indico.realtimefilter", {

        options: {
            callback: function(value) {},
            validation: function(e) { return true; },
            clearable: true,
            disableenter: true,
            emptyvalue: "",
            invalidclass: 'invalid',
            wait: 250
        },

        _create: function() {
            var self = this;
            var element = self.element;
            var opt = self.options;

            element.typeWatch({
                callback: function() {
                    self._callback();
                },
                wait: opt.wait,
                highlight: false,
                captureLength: 0
            });

            if (opt.clearable) {
                element.clearableinput({
                    onClear: function() {
                        self._callback();
                    },
                    emptyvalue: opt.emptyvalue
                });
            }

            element.on('cut paste', function() {
                self._delayedCallback();
            });

            element.on('focusout', function() {
                if ($(this).val() === "") {
                    $(this).val(opt.emptyvalue);
                }
            });

            if (opt.disableenter) {
                element.on('keydown', function(e) {
                    if (e.which == K.ENTER) {
                        e.preventDefault();
                    }
                });
            }
        },

        _callback: function() {
            var self = this;
            var element = self.element;
            var opt = self.options;

            if (opt.validation(element)) {
                element.removeClass(opt.invalidclass);
                opt.callback(element.val().trim());
            } else {
                element.addClass(opt.invalidclass);
            }
        },

        _delayedCallback: function() {
            var self = this;

            setTimeout(function() {
                self._callback();
            }, self.options.wait);
        },

        clear: function() {
            var self = this;
            self.setValue('');
        },

        setValue: function(value) {
            var self = this;
            if (self.options.clearable) {
                self.element.clearableinput('setValue', value);
            } else {
                self.element.val(value);
            }
        },

        update: function(delayed) {
            var self = this;

            if (delayed) {
                self._delayedCallback();
            } else {
                self._callback();
            }
        },

        validate: function() {
            var self = this;
            return self.options.validation(self.element);
        }
    });
})(jQuery);
<commit_msg>Fix realtimefilter not triggering callback<commit_after>/* This file is part of Indico.
 * Copyright (C) 2002 - 2016 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

(function($) {
    $.widget("indico.realtimefilter", {

        options: {
            callback: function(value) {},
            validation: function(e) { return true; },
            clearable: true,
            disableenter: true,
            emptyvalue: "",
            invalidclass: 'invalid',
            wait: 250
        },

        _create: function() {
            var self = this;
            var element = self.element;
            var opt = self.options;

            element.typeWatch({
                callback: function() {
                    self._callback();
                },
                wait: opt.wait,
                highlight: false,
                captureLength: 0
            });

            if (opt.clearable) {
                element.clearableinput({
                    onClear: function() {
                        self._callback();
                    },
                    emptyvalue: opt.emptyvalue
                });
            }

            element.on('cut paste', function() {
                self._delayedCallback();
            });

            element.on('focusout', function() {
                if ($(this).val() === "") {
                    $(this).val(opt.emptyvalue);
                }
            });

            if (opt.disableenter) {
                element.on('keydown', function(e) {
                    if (e.which == K.ENTER) {
                        e.preventDefault();
                    }
                });
            }
        },

        _callback: function() {
            var self = this;
            var element = self.element;
            var opt = self.options;

            if (opt.validation(element)) {
                element.removeClass(opt.invalidclass);
                opt.callback(element.val().trim());
            } else {
                element.addClass(opt.invalidclass);
            }
        },

        _delayedCallback: function() {
            var self = this;

            setTimeout(function() {
                self._callback();
            }, self.options.wait);
        },

        clear: function() {
            var self = this;
            self.setValue('');
        },

        setValue: function(value) {
            var self = this;
            if (self.options.clearable) {
                self.element.clearableinput('setValue', value);
            } else {
                self.element.val(value);
            }
            // Needed for typeWatch to refresh its timer
            self.element.trigger('input');
        },

        update: function(delayed) {
            var self = this;

            if (delayed) {
                self._delayedCallback();
            } else {
                self._callback();
            }
        },

        validate: function() {
            var self = this;
            return self.options.validation(self.element);
        }
    });
})(jQuery);
<|endoftext|>


<commit_before>var $ = require('jquery');
var WindowStorage = require('../utils/window-storage');

var RelatedPopups = function() {
    this.windowStorage = new WindowStorage('relatedWindows');
};

RelatedPopups.prototype = {
    updateLinks: function($select) {
        $select.find('~ .change-related, ~ .delete-related, ~ .add-another').each(function() {
            var $link = $(this);
            var hrefTemplate = $link.data('href-template');

            if (hrefTemplate == undefined) {
                return;
            }

            var value = $select.val();

            if (value) {
                $link.attr('href', hrefTemplate.replace('__fk__', value))
            } else {
                $link.removeAttr('href');
            }
        });
    },
    initLinks: function() {
        var self = this;

        $('.form-row select').each(function() {
            var $select = $(this);

            self.updateLinks($select);

            $select.find('~ .add-related, ~ .change-related, ~ .delete-related, ~ .add-another').each(function() {
                var $link = $(this);

                $link.on('click', function(e) {
                    e.preventDefault();

                    var href = $link.attr('href');

                    if (href != undefined) {
                        if (href.indexOf('_popup') == -1) {
                            href += (href.indexOf('?') == -1) ? '?_popup=1' : '&_popup=1';
                        }

                        self.showPopup($select, href);
                    }
                });
            });
        }).on('change', function() {
            self.updateLinks($(this));
        });

        $('.form-row input').each(function() {
            var $input = $(this);

            $input.find('~ .related-lookup').each(function() {
                var $link = $(this);

                $link.on('click', function(e) {
                    e.preventDefault();

                    var href = $link.attr('href');

                    href += (href.indexOf('?') == -1) ? '?_popup=1' : '&_popup=1';

                    self.showPopup($input, href);
                });
            });
        });
    },
    initPopupBackButton: function() {
        var self = this;

        $('.related-popup-back').on('click', function(e) {
            e.preventDefault();
            self.closePopup();
        });
    },
    showPopup: function($input, href) {
        var $document = $(window.top.document);
        var $container = $document.find('.related-popup-container');
        var $loading = $container.find('.loading-indicator');
        var $body = $document.find('body');
        var $popup = $('<div>')
            .addClass('related-popup')
            .data('input', $input);
        var $iframe = $('<iframe>')
            .attr('src', href)
            .on('load', function() {
                $popup.add($document.find('.related-popup-back')).fadeIn(200, 'swing', function() {
                    $loading.hide();
                });
            });

        $popup.append($iframe);
        $loading.show();
        $container.fadeIn(200, 'swing', function() {
            $container.append($popup);
        });
        $body.addClass('non-scrollable');
    },
    closePopup: function(response) {
        var previousWindow = this.windowStorage.previous();
        var self = this;

        (function($) {
            var $document = $(window.top.document);
            var $popups = $document.find('.related-popup');
            var $container = $document.find('.related-popup-container');
            var $popup = $popups.last();

            if (response != undefined) {
                self.processPopupResponse($popup, response);
            }

            self.windowStorage.pop();

            if ($popups.length == 1) {
                $container.fadeOut(200, 'swing', function() {
                    $document.find('.related-popup-back').hide();
                    $document.find('body').removeClass('non-scrollable');
                    $popup.remove();
                });
            } else {
                $popup.remove();
            }
        })(previousWindow ? previousWindow.jet.jQuery : $);
    },
    findPopupResponse: function() {
        var self = this;

        $('#django-admin-popup-response-constants').each(function() {
            var $constants = $(this);
            var response = $constants.data('popup-response');

            self.closePopup(response);
        });
    },
    processPopupResponse: function($popup, response) {
        var $input = $popup.data('input');

        switch (response.action) {
            case 'change':
                $input.find('option').each(function() {
                    var $option = $(this);

                    if ($option.val() == response.value) {
                        $option.html(response.obj).val(response.new_value);
                    }
                });

                $input.trigger('change').trigger('select:init');

                break;
            case 'delete':
                $input.find('option').each(function() {
                    var $option = $(this);

                    if ($option.val() == response.value) {
                        $option.remove();
                    }
                });

                $input.trigger('change').trigger('select:init');

                break;
            default:
                if ($input.is('select')) {
                    var $option = $('<option>')
                        .val(response.value)
                        .html(response.obj);

                    $input.append($option);
                    $option.attr('selected', true);

                    $input
                        .trigger('change')
                        .trigger('select:init');
                } else if ($input.is('input.vManyToManyRawIdAdminField') && $input.val()) {
                    $input.val($input.val() + ',' + response.value);
                } else if ($input.is('input')) {
                    $input.val(response.value);
                }

                break;
        }
    },
    overrideRelatedGlobals: function() {
        var self = this;

        window.showRelatedObjectLookupPopup
            = window.showAddAnotherPopup
            = window.showRelatedObjectPopup
            = function() { };

        window.opener = this.windowStorage.previous();
        window.dismissRelatedLookupPopup = function(win, chosenId) {
            self.closePopup({
                action: 'lookup',
                value: chosenId
            });
        };
    },
    initDeleteRelatedCancellation: function() {
        var self = this;

        $('.popup.delete-confirmation .cancel-link').on('click', function(e) {
            e.preventDefault();
            self.closePopup();
        }).removeAttr('onclick');
    },
    initLookupLinks: function() {
        var self = this;

        $("a[data-popup-opener]").click(function(e) {
            e.preventDefault();

            self.closePopup({
                action: 'lookup',
                value: $(this).data("popup-opener")
            });
        });
    },
    run: function() {
        this.windowStorage.push(window);

        try {
            this.initLinks();
            this.initPopupBackButton();
            this.findPopupResponse();
            this.overrideRelatedGlobals();
            this.initDeleteRelatedCancellation();
            this.initLookupLinks();
        } catch (e) {
            console.error(e, e.stack);
        }
    }
};

$(document).ready(function() {
    new RelatedPopups().run();
});
<commit_msg>Add loading to nested popups<commit_after>var $ = require('jquery');
var WindowStorage = require('../utils/window-storage');

var RelatedPopups = function() {
    this.windowStorage = new WindowStorage('relatedWindows');
};

RelatedPopups.prototype = {
    updateLinks: function($select) {
        $select.find('~ .change-related, ~ .delete-related, ~ .add-another').each(function() {
            var $link = $(this);
            var hrefTemplate = $link.data('href-template');

            if (hrefTemplate == undefined) {
                return;
            }

            var value = $select.val();

            if (value) {
                $link.attr('href', hrefTemplate.replace('__fk__', value))
            } else {
                $link.removeAttr('href');
            }
        });
    },
    initLinks: function() {
        var self = this;

        $('.form-row select').each(function() {
            var $select = $(this);

            self.updateLinks($select);

            $select.find('~ .add-related, ~ .change-related, ~ .delete-related, ~ .add-another').each(function() {
                var $link = $(this);

                $link.on('click', function(e) {
                    e.preventDefault();

                    var href = $link.attr('href');

                    if (href != undefined) {
                        if (href.indexOf('_popup') == -1) {
                            href += (href.indexOf('?') == -1) ? '?_popup=1' : '&_popup=1';
                        }

                        self.showPopup($select, href);
                    }
                });
            });
        }).on('change', function() {
            self.updateLinks($(this));
        });

        $('.form-row input').each(function() {
            var $input = $(this);

            $input.find('~ .related-lookup').each(function() {
                var $link = $(this);

                $link.on('click', function(e) {
                    e.preventDefault();

                    var href = $link.attr('href');

                    href += (href.indexOf('?') == -1) ? '?_popup=1' : '&_popup=1';

                    self.showPopup($input, href);
                });
            });
        });
    },
    initPopupBackButton: function() {
        var self = this;

        $('.related-popup-back').on('click', function(e) {
            e.preventDefault();
            self.closePopup();
        });
    },
    showPopup: function($input, href) {
        var $document = $(window.top.document);
        var $container = $document.find('.related-popup-container');
        var $loading = $container.find('.loading-indicator');
        var $body = $document.find('body');
        var $popup = $('<div>')
            .addClass('related-popup')
            .data('input', $input);
        var $iframe = $('<iframe>')
            .attr('src', href)
            .on('load', function() {
                $popup.add($document.find('.related-popup-back')).fadeIn(200, 'swing', function() {
                    $loading.hide();
                });
            });

        $popup.append($iframe);
        $loading.show();
        $document.find('.related-popup').add($document.find('.related-popup-back')).fadeOut(200, 'swing');
        $container.fadeIn(200, 'swing', function() {
            $container.append($popup);
        });
        $body.addClass('non-scrollable');
    },
    closePopup: function(response) {
        var previousWindow = this.windowStorage.previous();
        var self = this;

        (function($) {
            var $document = $(window.top.document);
            var $popups = $document.find('.related-popup');
            var $container = $document.find('.related-popup-container');
            var $popup = $popups.last();

            if (response != undefined) {
                self.processPopupResponse($popup, response);
            }

            self.windowStorage.pop();

            if ($popups.length == 1) {
                $container.fadeOut(200, 'swing', function() {
                    $document.find('.related-popup-back').hide();
                    $document.find('body').removeClass('non-scrollable');
                    $popup.remove();
                });
            } else if ($popups.length > 1) {
                $popup.remove();
                $popups.eq($popups.length - 2).show();
            }
        })(previousWindow ? previousWindow.jet.jQuery : $);
    },
    findPopupResponse: function() {
        var self = this;

        $('#django-admin-popup-response-constants').each(function() {
            var $constants = $(this);
            var response = $constants.data('popup-response');

            self.closePopup(response);
        });
    },
    processPopupResponse: function($popup, response) {
        var $input = $popup.data('input');

        switch (response.action) {
            case 'change':
                $input.find('option').each(function() {
                    var $option = $(this);

                    if ($option.val() == response.value) {
                        $option.html(response.obj).val(response.new_value);
                    }
                });

                $input.trigger('change').trigger('select:init');

                break;
            case 'delete':
                $input.find('option').each(function() {
                    var $option = $(this);

                    if ($option.val() == response.value) {
                        $option.remove();
                    }
                });

                $input.trigger('change').trigger('select:init');

                break;
            default:
                if ($input.is('select')) {
                    var $option = $('<option>')
                        .val(response.value)
                        .html(response.obj);

                    $input.append($option);
                    $option.attr('selected', true);

                    $input
                        .trigger('change')
                        .trigger('select:init');
                } else if ($input.is('input.vManyToManyRawIdAdminField') && $input.val()) {
                    $input.val($input.val() + ',' + response.value);
                } else if ($input.is('input')) {
                    $input.val(response.value);
                }

                break;
        }
    },
    overrideRelatedGlobals: function() {
        var self = this;

        window.showRelatedObjectLookupPopup
            = window.showAddAnotherPopup
            = window.showRelatedObjectPopup
            = function() { };

        window.opener = this.windowStorage.previous();
        window.dismissRelatedLookupPopup = function(win, chosenId) {
            self.closePopup({
                action: 'lookup',
                value: chosenId
            });
        };
    },
    initDeleteRelatedCancellation: function() {
        var self = this;

        $('.popup.delete-confirmation .cancel-link').on('click', function(e) {
            e.preventDefault();
            self.closePopup();
        }).removeAttr('onclick');
    },
    initLookupLinks: function() {
        var self = this;

        $("a[data-popup-opener]").click(function(e) {
            e.preventDefault();

            self.closePopup({
                action: 'lookup',
                value: $(this).data("popup-opener")
            });
        });
    },
    run: function() {
        this.windowStorage.push(window);

        try {
            this.initLinks();
            this.initPopupBackButton();
            this.findPopupResponse();
            this.overrideRelatedGlobals();
            this.initDeleteRelatedCancellation();
            this.initLookupLinks();
        } catch (e) {
            console.error(e, e.stack);
        }
    }
};

$(document).ready(function() {
    new RelatedPopups().run();
});
<|endoftext|>


<commit_before>/**
 * Basic presets: swiss direct matchings, round similar to chess, and ko
 * with a matched cadrage. Simple rankings
 *
 * @return Presets
 * @author Erik E. Lorenz <erik@tuvero.de>
 * @license MIT License
 * @see LICENSE
 */

define(function () {
  var Presets;

  Presets = {
    target: "basic",
    systems: {
      swiss: {
        ranking: ["wins", "headtohead", "saldo"],
        mode: "ranks"
      },
      ko: {
        mode: "matched"
      },
      round: {
        ranking: ["wins", "sonneborn", "headtohead", "points"]
      },
      placement: {}
    },
    ranking: {
      components: ["buchholz", "finebuchholz", "points", "saldo", "sonneborn",
        "numgames", "wins", "headtohead", "threepoint", "twopoint"
      ]
    },
    registration: {
      defaultteamsize: 1,
      minteamsize: 1,
      maxteamsize: 1,
      teamsizeicon: false
    },
    names: {
      playernameurl: "",
      dbplayername: "tuverobasicplayers",
      apitoken: "apitoken",
      teamsfile: "tuvero-anmeldungen.txt"
    },
    ui: {
      rankingpoints: false
    }
  };

  return Presets;
});<commit_msg>Remove "Tuvero Basic" maxteams restriction<commit_after>/**
 * Basic presets: swiss direct matchings, round similar to chess, and ko
 * with a matched cadrage. Simple rankings
 *
 * @return Presets
 * @author Erik E. Lorenz <erik@tuvero.de>
 * @license MIT License
 * @see LICENSE
 */

define(function () {
  var Presets;

  Presets = {
    target: "basic",
    systems: {
      swiss: {
        ranking: ["wins", "headtohead", "saldo"],
        mode: "ranks"
      },
      ko: {
        mode: "matched"
      },
      round: {
        ranking: ["wins", "sonneborn", "headtohead", "points"]
      },
      placement: {}
    },
    ranking: {
      components: ["buchholz", "finebuchholz", "points", "saldo", "sonneborn",
        "numgames", "wins", "headtohead", "threepoint", "twopoint"
      ]
    },
    registration: {
      defaultteamsize: 1,
      minteamsize: 1,
      maxteamsize: 3,
      teamsizeicon: false
    },
    names: {
      playernameurl: "",
      dbplayername: "tuverobasicplayers",
      apitoken: "apitoken",
      teamsfile: "tuvero-anmeldungen.txt"
    },
    ui: {
      rankingpoints: false
    }
  };

  return Presets;
});<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var passport = require('passport');
var login = require('connect-ensure-login');
var fs = require("fs-extra");
var bodyParser = require('body-parser');
var config = require("./config");
var uuid = require('node-uuid');
var crypto = require("crypto");
var dataModel = require("./dataModel");
var when = require("promised-io/promise").when;
var bcrypt = require('bcrypt');

exports.index = [
	login.ensureLoggedIn(),
	function(req, res) {
		if (req.isAuthenticated() && req.user && req.user.roles && (req.user.roles.indexOf("admin")>=0)){
			return res.render("admin", { title: "User Administration", request:req });
		}
		res.redirect(302, "/user/" + req.user.id);
//		res.render('index', { title: 'User Service', request: req});
	}
]

exports.loginForm = function(req, res) {
	console.log("Render Login Form");
	console.log('req: ', req);
  	res.render('login', {title: "Login Form", request: req});
};

function generateBearerToken(user,req){
	var name = user.username || user.id;
	var tokenid = uuid.v4().toString()
	var exp = new Date(); exp.setDate(exp.getDate()+1);
	var expiration=Math.floor(exp.valueOf()/1000);
	var realm = config.get('realm');

	var payload = [
		"un=" + name + "@" + realm, "tokenid=" + tokenid,
		"expiry="+expiration,"client_id=" + name + "@" + realm,
		"token_type=" + "Bearer","realm=" + realm
	];

	payload.push("SigningSubject=" + config.get("signingSubjectURL"));

	var key = SigningPEM.toString('ascii');
        var sign = crypto.createSign("RSA-SHA1");
	sign.update(payload.join("|"));
	var signature = sign.sign(key,'hex');
	var token = payload.join("|") + "|sig=" + signature;
	console.log("New Bearer Token: ", token);
	return token;
}

exports.login = [
	bodyParser.urlencoded({extended:true}),
	function(req,res,next){
		passport.authenticate('local', function(err,user,info){
			console.log("local auth: ", user, info, req.query);
			if (err) { return next(err); }
			if (!user) { return res.redirect('/login'); }

			req.logIn(user, function(err) {
				if (err) { return next(err); }

				if (user && req.session) {
					delete user.password;
					req.session.userProfile = user;
					req.session.authorizationToken = generateBearerToken(user,req);
				}else{
					console.log("NO Session");
				}

				if (req.query.application_id){
					if (req.query.application_id=="patric3"){
						res.write("");
						res.end();
						return;
//						return res.redirect(302, config.get("patric3_webapp_callbackURL"));
					}
				}
				return res.redirect(302,'/'); // + user.username);
				next();
			});

		})(req,res,next);
	}
]

exports.logout = function(req, res) {
  req.logout();
  res.redirect('/');
}
exports.register = [
	login.ensureLoggedOut({redirectTo: "/"}),
	function(req,res,next){
		res.render("registration",{title: "PATRIC Registration", request:req,error:false,formData:{}});
	}
]
exports.handleRegistration = [
	login.ensureLoggedOut(),
	function(req,res,next){
		//console.log("registration parameters: ", req.body);
		var UserModel = dataModel.get("user");
		when(UserModel.registerUser(req.body), function(user){
			res.render("registration_complete", {title: "Registration Complete", request: req});
		}, function(err){
			console.log("Registration Error: ", err);
			res.render("registration",{title: "PATRIC Registration", request:req, error:err, formData: req.body});
		});
	}
];

exports.performResetWithCode = [
//	login.ensureLoggedOut({redirectTo: "/"}),
	function(req,res,next){
		console.log("req.params: ", req.params);
		if (!req.params.email || ! req.params.code) {
			return res.render("do_reset", {title: "PASSWORD RESET", request:req});
		}

		var UserModel = dataModel.get('user');
		var query = "and(eq(resetCode," + encodeURIComponent(req.params.code) + "),eq(email," + encodeURIComponent(req.params.email) + "))";
		console.log("Query: ", query);
		when(UserModel.query(query),function(results) {
			console.log("Perform Reset Search Results: ", results.results);;
			if (results.results && results.results.length==1) {
				var user = results.results[0];
				console.log("Change Password for User: ", user);
				res.render("change_password",{title: "Set New Password", request:req});
			}
		});
	}
];

exports.requestResetPassword = [
	login.ensureLoggedOut({redirectTo: "/"}),
	function(req,res,next){
		console.log("Render Reset Password Form");
		res.render("reset_password",{title: "PATRIC Registration", request:req});
	}

];
exports.resetPassword = [
	function(req,res,next) {
                var UserModel = dataModel.get("user");
		if (req.body.email) {
	                return when(UserModel.resetAccount(req.body.email,{mail_user:true}), function(user){
				res.render("reset_complete", {title: "Reset Complete", request: req});
			});
                }

		next(new Error("Missing Email Address"));
	}

];
exports.changePasswordForm = [
	login.ensureLoggedIn({redirectTo: "/login"}),
	function(req,res,next){
		res.render("change_password",{title: "Change Password", request:req});
	}

];
exports.changePassword = [
	function(req,res,next){
		if (req.isAuthenticated && req.isAuthenticated()) {
			console.log("Change password for authenticated User");
			req.change_password_user = req.user;
			return next();
		}

		console.log("Req.body: ", req.body);

		if (req.body && req.body.code && req.body.email) {
			var UserModel = dataModel.get('user');
			var query = "and(eq(resetCode," + encodeURIComponent(req.body.code) + "),eq(email," + encodeURIComponent(req.body.email) + "))";
			console.log("Query: ", query);
			when(UserModel.query(query),function(results) {
	                        console.log("Perform Reset Search Results: ", results.results);;
				if (results && results.results && results.results.length>0) {
					req.change_password_user = results.results[0];
					return next();
				}
				next(new Error("Not Authorized"));
                	});

		}
	},

	function(req,res,next){
		if (req.change_password_user && req.body.password){
			console.log("SAVE NEW PASSWORD: ", req.body.password);
			var UserModel = dataModel.get("user");
			when(UserModel.setPassword(req.change_password_user.id, req.body.password),function(){
				res.redirect("/");
			},next);
		}
	}
];

exports.validateUserCredentials = [
	bodyParser.urlencoded({extended:true}),
	function(req,res,next){
		when(dataModel.get("user").get(req.body.username),function(user){
			if (!user || !user.password){
				res.status(401);
				res.end();
				return;
			}
			console.log("Login Check for: ", user, req.body.password);
			bcrypt.compare(req.body.password,user.password, function(err,results){
				if (err || !results) {
					res.status(401)
					res.end();
					return;
				}

				res.status(204);
				res.end();
			})
		}, function(err){
			res.status(401)
			res.end();
		});
	}
]
<commit_msg>bump lifetime up to match globus<commit_after>/**
 * Module dependencies.
 */
var passport = require('passport');
var login = require('connect-ensure-login');
var fs = require("fs-extra");
var bodyParser = require('body-parser');
var config = require("./config");
var uuid = require('node-uuid');
var crypto = require("crypto");
var dataModel = require("./dataModel");
var when = require("promised-io/promise").when;
var bcrypt = require('bcrypt');

exports.index = [
	login.ensureLoggedIn(),
	function(req, res) {
		if (req.isAuthenticated() && req.user && req.user.roles && (req.user.roles.indexOf("admin")>=0)){
			return res.render("admin", { title: "User Administration", request:req });
		}
		res.redirect(302, "/user/" + req.user.id);
//		res.render('index', { title: 'User Service', request: req});
	}
]

exports.loginForm = function(req, res) {
	console.log("Render Login Form");
	console.log('req: ', req);
  	res.render('login', {title: "Login Form", request: req});
};

function generateBearerToken(user,req){
	var name = user.username || user.id;
	var tokenid = uuid.v4().toString()
	var exp = new Date(); exp.setDate(exp.getDate()+182);
	var expiration=Math.floor(exp.valueOf()/1000);
	var realm = config.get('realm');

	var payload = [
		"un=" + name + "@" + realm, "tokenid=" + tokenid,
		"expiry="+expiration,"client_id=" + name + "@" + realm,
		"token_type=" + "Bearer","realm=" + realm
	];

	payload.push("SigningSubject=" + config.get("signingSubjectURL"));

	var key = SigningPEM.toString('ascii');
        var sign = crypto.createSign("RSA-SHA1");
	sign.update(payload.join("|"));
	var signature = sign.sign(key,'hex');
	var token = payload.join("|") + "|sig=" + signature;
	console.log("New Bearer Token: ", token);
	return token;
}

exports.login = [
	bodyParser.urlencoded({extended:true}),
	function(req,res,next){
		passport.authenticate('local', function(err,user,info){
			console.log("local auth: ", user, info, req.query);
			if (err) { return next(err); }
			if (!user) { return res.redirect('/login'); }

			req.logIn(user, function(err) {
				if (err) { return next(err); }

				if (user && req.session) {
					delete user.password;
					req.session.userProfile = user;
					req.session.authorizationToken = generateBearerToken(user,req);
				}else{
					console.log("NO Session");
				}

				if (req.query.application_id){
					if (req.query.application_id=="patric3"){
						res.write("");
						res.end();
						return;
//						return res.redirect(302, config.get("patric3_webapp_callbackURL"));
					}
				}
				return res.redirect(302,'/'); // + user.username);
				next();
			});

		})(req,res,next);
	}
]

exports.logout = function(req, res) {
  req.logout();
  res.redirect('/');
}
exports.register = [
	login.ensureLoggedOut({redirectTo: "/"}),
	function(req,res,next){
		res.render("registration",{title: "PATRIC Registration", request:req,error:false,formData:{}});
	}
]
exports.handleRegistration = [
	login.ensureLoggedOut(),
	function(req,res,next){
		//console.log("registration parameters: ", req.body);
		var UserModel = dataModel.get("user");
		when(UserModel.registerUser(req.body), function(user){
			res.render("registration_complete", {title: "Registration Complete", request: req});
		}, function(err){
			console.log("Registration Error: ", err);
			res.render("registration",{title: "PATRIC Registration", request:req, error:err, formData: req.body});
		});
	}
];

exports.performResetWithCode = [
//	login.ensureLoggedOut({redirectTo: "/"}),
	function(req,res,next){
		console.log("req.params: ", req.params);
		if (!req.params.email || ! req.params.code) {
			return res.render("do_reset", {title: "PASSWORD RESET", request:req});
		}

		var UserModel = dataModel.get('user');
		var query = "and(eq(resetCode," + encodeURIComponent(req.params.code) + "),eq(email," + encodeURIComponent(req.params.email) + "))";
		console.log("Query: ", query);
		when(UserModel.query(query),function(results) {
			console.log("Perform Reset Search Results: ", results.results);;
			if (results.results && results.results.length==1) {
				var user = results.results[0];
				console.log("Change Password for User: ", user);
				res.render("change_password",{title: "Set New Password", request:req});
			}
		});
	}
];

exports.requestResetPassword = [
	login.ensureLoggedOut({redirectTo: "/"}),
	function(req,res,next){
		console.log("Render Reset Password Form");
		res.render("reset_password",{title: "PATRIC Registration", request:req});
	}

];
exports.resetPassword = [
	function(req,res,next) {
                var UserModel = dataModel.get("user");
		if (req.body.email) {
	                return when(UserModel.resetAccount(req.body.email,{mail_user:true}), function(user){
				res.render("reset_complete", {title: "Reset Complete", request: req});
			});
                }

		next(new Error("Missing Email Address"));
	}

];
exports.changePasswordForm = [
	login.ensureLoggedIn({redirectTo: "/login"}),
	function(req,res,next){
		res.render("change_password",{title: "Change Password", request:req});
	}

];
exports.changePassword = [
	function(req,res,next){
		if (req.isAuthenticated && req.isAuthenticated()) {
			console.log("Change password for authenticated User");
			req.change_password_user = req.user;
			return next();
		}

		console.log("Req.body: ", req.body);

		if (req.body && req.body.code && req.body.email) {
			var UserModel = dataModel.get('user');
			var query = "and(eq(resetCode," + encodeURIComponent(req.body.code) + "),eq(email," + encodeURIComponent(req.body.email) + "))";
			console.log("Query: ", query);
			when(UserModel.query(query),function(results) {
	                        console.log("Perform Reset Search Results: ", results.results);;
				if (results && results.results && results.results.length>0) {
					req.change_password_user = results.results[0];
					return next();
				}
				next(new Error("Not Authorized"));
                	});

		}
	},

	function(req,res,next){
		if (req.change_password_user && req.body.password){
			console.log("SAVE NEW PASSWORD: ", req.body.password);
			var UserModel = dataModel.get("user");
			when(UserModel.setPassword(req.change_password_user.id, req.body.password),function(){
				res.redirect("/");
			},next);
		}
	}
];

exports.validateUserCredentials = [
	bodyParser.urlencoded({extended:true}),
	function(req,res,next){
		when(dataModel.get("user").get(req.body.username),function(user){
			if (!user || !user.password){
				res.status(401);
				res.end();
				return;
			}
			console.log("Login Check for: ", user, req.body.password);
			bcrypt.compare(req.body.password,user.password, function(err,results){
				if (err || !results) {
					res.status(401)
					res.end();
					return;
				}

				res.status(204);
				res.end();
			})
		}, function(err){
			res.status(401)
			res.end();
		});
	}
]
<|endoftext|>


<commit_before>/**
 * Created by Alexander Lex on 3/4/14.
 */

var SET_SIZE_GROUP_PREFIX = 'SetSizeG_';
var EMPTY_GROUP_ID = 'EmptyGroup';
var SET_BASED_GROUPING_PREFIX = "SetG_";

var handleLogicGroups = function (subsets, level, parentID) {
    filterGroups = [];
    UpSetState.logicGroups.forEach(function (d) {
        var group = new QueryGroup(d.id, d.groupName, d.orClauses);
        var maskList = d.getListOfValues();

        getSubsetsForMaskList(subsets, maskList, function (d) {
            group.addSubSet(d);
        });

        filterGroups.push(group)

    })
}

var groupByOverlapDegree = function (subSets, level, parentID) {
    var degree = 2;
    var newGroups = []

    var combinations = Math.pow(2, usedSets.length) - 1;

    var queries = []
    for (var i = 0; i <= combinations; i++) {
        fillMasks(i, usedSets.length, 2, queries);

    }
    for (var i = 0; i < queries.length; i++) {
        var name = "";
        for (var j = 0; j < queries[i].length; j++) {
            if (queries[i][j] === 1) {
                name += usedSets[j].elementName + " ";
            }
        }
        var group = new QueryGroup("Overlap_G_" + i + "_" + + parentID, name, queries[i]);
        getSubsetsForMaskList(subSets, [queries[i]], function (d) {
            group.addSubSet(d);
        });
        if (group.subSets.length > 0) {
            newGroups.unshift(group);
        }
    }

    return newGroups;
//    console.log(queries);

//    for (var i = 0; i < subSets.length; i++) {
//        mask = Array.apply(null, new Array(subSets.length)).map(Number.prototype.valueOf, 0);
//        mask[i] = 1;
//    }

}

var fillMasks = function (setMask, length, minSets, queries) {

    var bitMask = 1;

    var query = Array.apply(null, new Array(length)).map(Number.prototype.valueOf, 0);

    var memberCount = 0;

    for (var setIndex = length - 1; setIndex >= 0; setIndex--) {
        if ((setMask & bitMask) === 1) {
            query[setIndex] = 1;
            memberCount++;
        }
        else {
            query[setIndex] = 2;
        }
        setMask = setMask >> 1;
    }
    if (memberCount == minSets) {
        queries.push(query);
    }

//    var resultMasks = [];
//    for (var maskCount = 0; maskCount < length; maskCount++) {
//        for (var i = 0; i < length; i++) {
//            var newMask = masks[maskCount].slice(0);
//
//
//        }
//    }
}

var groupByRelevanceMeasure = function (subSets, level, parentID) {
    var newGroups = [];
    newGroups.push(new Group('GROUP_POS_DEV' + parentID, 'Positive Expected Value', level));
    newGroups.push(new Group('GROUP_NEG_DEV' + parentID, 'Negative Expected Value', level));
    newGroups.push(new Group(EMPTY_GROUP_ID + parentID, 'Empty Subset', level));
    for (var i = 0; i < subSets.length; i++) {
        var index = 0
        if (subSets[i].disproportionality > 0) {
            index = 0;
        }
        else if (subSets[i].disproportionality < 0) {
            index = 1;
        }
        else {
            index = 2;
        }
        newGroups[index].addSubSet(subSets[i])
    }
    return newGroups;
}

var groupByIntersectionSize = function (subSets, level, parentID) {
    var newGroups = [];
    newGroups.push(new Group(EMPTY_GROUP_ID + parentID, 'Empty Subset', level));
    var maxSetSize = Math.min(usedSets.length, UpSetState.maxCardinality);
    for (var i = UpSetState.minCardinality; i < maxSetSize; i++) {
        newGroups.push(new Group(SET_SIZE_GROUP_PREFIX + (i + 1) + '_' + parentID, (i + 1) + '-Set Subsets', level));
    }
    subSets.forEach(function (subSet) {
        var group = newGroups[subSet.nrCombinedSets];
        if (group != null)
            group.addSubSet(subSet);
        else
            console.log('Fail ' + group + subSet.nrCombinedSets);
    })
    return newGroups;
}

/**
 * Creates groups for all sets containing all subsets of this set
 */
var groupBySet = function (subSets, level, parentID) {

    // TODO add empty subset

    var newGroups = [];
    newGroups.push(new Group(EMPTY_GROUP_ID, 'Empty Subset', level));
    for (var i = 0; i < usedSets.length; i++) {
        var group = new Group(SET_BASED_GROUPING_PREFIX + (i + 1) + parentID, usedSets[i].elementName, level);

        newGroups.push(group);

        subSets.forEach(function (subSet) {
            if (subSet.combinedSets[i] !== 0) {
                group.addSubSet(subSet);
            }
        });
    }
    return newGroups;
};

/** Collapse or uncollapse group */
var collapseGroup = function (group) {
    group.isCollapsed = !group.isCollapsed;

    UpSetState.collapseChanged = true;
    updateState();
    return;

};

var collapseAggregate = function (aggregate) {
    aggregate.isCollapsed = !aggregate.isCollapsed;
    updateState();
};

// ----------------------- Sort Functions ----------------------------

/** Filters the provided list of subsets to include only those of length >0. If no list of subsets is provided the global list is used. */
function getFilteredSubSets(subSetsToFilter) {
    if (!subSetsToFilter) {
        subSetsToFilter = subSets;
    }
    if (!UpSetState.hideEmpties) {
        return subSetsToFilter.slice(0);
    }
    var filteredSubSets = []
    for (var i = 0; i < subSetsToFilter.length; i++) {
        if (subSetsToFilter[i].items.length > 0) {
            filteredSubSets.push(subSetsToFilter[i]);
        }
    }
    return filteredSubSets;
}

var sortBySetItem = function (subSets, set) {
    if (!set) {
        set = usedSets[0];
    }
    var dataRows = getFilteredSubSets(subSets);
    var setIndex = usedSets.indexOf(set);
    dataRows.sort(function (a, b) {
        // move all elements that contain the clicked set to the top
        if (b.combinedSets[setIndex] !== a.combinedSets[setIndex]) {
            return b.combinedSets[setIndex] - a.combinedSets[setIndex];
        }
        // move all elements with fewer intersections to the top
        if (a.nrCombinedSets !== b.nrCombinedSets) {
            return a.nrCombinedSets - b.nrCombinedSets;
        }
        // if the number of combined sets is identical, we can pick the largest one
        return b.id - a.id;
    });
    return dataRows;
}

var sortByCombinationSize = function (subSets) {
    var dataRows = getFilteredSubSets(subSets);

// sort by number of combinations
    dataRows.sort(function (a, b) {
        if (a.nrCombinedSets !== b.nrCombinedSets) {
            return a.nrCombinedSets - b.nrCombinedSets;
        }
        // if the number of combined sets is identical, we can pick the largest one
        return b.id - a.id;
    });
    return dataRows;
}

/** sort by size of set overlap */
var sortBySubSetSize = function (subSets) {
    var dataRows = getFilteredSubSets(subSets);
    dataRows.sort(function (a, b) {
        return b.setSize - a.setSize;
    });
    return dataRows;
}

/** sort by size of set overlap */
var sortByExpectedValue = function (subSets) {
    var dataRows = getFilteredSubSets(subSets);

    dataRows.sort(function (a, b) {
        return Math.abs(b.disproportionality) - Math.abs(a.disproportionality);
    });
    return dataRows;
}

/**
 * Takes a list of groups and writes them into an array, according to the nesting & collapse rules
 * @param groupList
 * @returns {*}
 */
var unwrapGroups = function (groupList) {
    var dataRows = []
    for (var i = 0; i < groupList.length; i++) {
        var group = groupList[i];
        // ignoring an empty empty group
        if (group.id === EMPTY_GROUP_ID && group.setSize === 0 || (group.visibleSets.length === 0 && UpSetState.hideEmpties)) {
            continue;
        }
        dataRows.push(group);
        if (UpSetState.collapseAll) {
            group.isCollapsed = true;
        }
        if (UpSetState.expandAll) {
            group.isCollapsed = false;
        }
        if (UpSetState.levelTwoGrouping && group.nestedGroups) {
            dataRows = dataRows.concat(unwrapGroups(group.nestedGroups, []));
            continue;
        }
        if (!group.isCollapsed) {
            dataRows = dataRows.concat(StateMap[UpSetState.sorting](group.visibleSets));

            if (group.aggregate.subSets.length > 0 && !UpSetState.hideEmpties) {
                dataRows.push(group.aggregate);
                if (!group.aggregate.isCollapsed) {
                    for (var k = 0; k < group.aggregate.subSets.length; k++) {
                        dataRows.push(group.aggregate.subSets[k]);
                    }
                }
            }
        }
    }

    return dataRows;
};

var StateMap = {
    groupByIntersectionSize: groupByIntersectionSize,
    groupBySet: groupBySet,
    groupByRelevanceMeasure: groupByRelevanceMeasure,
    groupByOverlapDegree: groupByOverlapDegree,

    sortByCombinationSize: sortByCombinationSize,
    sortBySubSetSize: sortBySubSetSize,
    sortByExpectedValue: sortByExpectedValue,
    sortBySubSetSize: sortBySubSetSize,
    sortBySetItem: sortBySetItem
};

var StateOpt = {
    groupByIntersectionSize: 'groupByIntersectionSize',
    groupBySet: 'groupBySet',
    groupByRelevanceMeasure: 'groupByRelevanceMeasure',
    groupByOverlapDegree: 'groupByOverlapDegree',

    sortByCombinationSize: 'sortByCombinationSize',
    sortBySubSetSize: 'sortBySubSetSize',
    sortByExpectedValue: 'sortByExpectedValue',
    sortBySetItem: 'sortBySetItem'
};

var UpSetState = {
    collapseAll: false,
    expandAll: false,
    // collapseChanged: false,

    grouping: queryParameters["grouping"] || StateOpt.groupBySet,
    levelTwoGrouping: undefined,
    sorting: StateOpt.sortByCombinationSize,

    /** hide empty subsets, groups and aggregates */
    hideEmpties: true,

    /** Sets the upper threshold of cardinality of subsets */
    maxCardinality: undefined,
    /** Sets the lower threshold of cardinality of subsets */
    minCardinality: 0,

    forceUpdate: false,

    /** user defined logic groups **/
    logicGroups: [],
    logicGroupChanged: false

};

var previousState = false;

var updateState = function (parameter) {
    var forceUpdate = !previousState || UpSetState.forceUpdate || (UpSetState.hideEmpties != previousState.hideEmpties);

    // true if pure sorting - no grouping
    if ((UpSetState.sorting && !UpSetState.grouping) && (forceUpdate || (previousState && previousState.sorting !== UpSetState.sorting))) {
        dataRows = StateMap[StateOpt[UpSetState.sorting]](subSets, parameter);
    }
    else if (UpSetState.grouping && (forceUpdate || (previousState && previousState.grouping !== UpSetState.grouping || previousState.levelTwoGrouping !== UpSetState.levelTwoGrouping))) {
        levelOneGroups = StateMap[StateOpt[UpSetState.grouping]](subSets, 1, "");

        if (UpSetState.levelTwoGrouping) {
            levelOneGroups.forEach(function (group) {
                group.nestedGroups = StateMap[StateOpt[UpSetState.levelTwoGrouping]](group.subSets, 2, group.id);
            });
        }
        dataRows = unwrapGroups(levelOneGroups);

    }
    else if (UpSetState.collapseChanged && UpSetState.grouping) {
        dataRows = unwrapGroups(levelOneGroups);
    }

    if (UpSetState.logicGroupChanged) {
        handleLogicGroups(subSets, 1);
        UpSetState.logicGroupChanged = false;

    }

    if (filterGroups && filterGroups.length > 0) {
        var filteredRows = unwrapGroups(filterGroups);
        var separator = new Separator("FILTER_SEPARATOR", 'Natural Intersections');
        filteredRows.push(separator);
        dataRows = filteredRows.concat(dataRows);
    }

    UpSetState.forceUpdate = false;
    UpSetState.expandAll = false;
    UpSetState.collapseAll = false;
    UpSetState.collapseChanged = false;

    renderRows.length = 0;

    var registry = {};
    var prefix = "";

    var count = 1;
    dataRows.forEach(function (element) {
        var wrapper = {};

        if (UpSetState.grouping === StateOpt.groupBySet || UpSetState.levelTwoGrouping === StateOpt.groupBySet) {
            if (element.type === ROW_TYPE.SUBSET) {
                wrapper.id = prefix + element.id;
            }
            else {
                prefix = element.id + "_";
                wrapper.id = element.id;
            }
        }
        else {

            if (registry.hasOwnProperty(element.id)) {
                count = registry[element.id];
                count += 1;
                registry[element.id] = count;
            }
            else {
                registry[element.id] = 1;
            }

            wrapper.id = element.id + '_' + count;
        }
        wrapper.data = element;
        renderRows.push(wrapper);

    });
    previousState = JSON.parse(JSON.stringify(UpSetState));

    queryParameters["grouping"] = UpSetState.grouping;
    updateQueryParameters();

};
<commit_msg>Some bugfixing towards #132<commit_after>/**
 * Created by Alexander Lex on 3/4/14.
 */

var SET_SIZE_GROUP_PREFIX = 'SetSizeG_';
var EMPTY_GROUP_ID = 'EmptyGroup';
var SET_BASED_GROUPING_PREFIX = "SetG_";

var handleLogicGroups = function (subsets, level, parentGroup) {
    filterGroups = [];
    UpSetState.logicGroups.forEach(function (d) {
        var group = new QueryGroup(d.id, d.groupName, d.orClauses);
        var maskList = d.getListOfValues();

        getSubsetsForMaskList(subsets, maskList, function (d) {
            group.addSubSet(d);
        });

        filterGroups.push(group)

    })
}

var groupByOverlapDegree = function (subSets, level, parentGroup) {
    var degree = 2;
    var newGroups = []

    var combinations = Math.pow(2, usedSets.length) - 1;

    var queries = []
    for (var i = 0; i <= combinations; i++) {
        fillMasks(i, usedSets.length, 2, queries);
    }
    for (var i = 0; i < queries.length; i++) {
        var name = "";
        for (var j = 0; j < queries[i].length; j++) {
            if (queries[i][j] === 1) {
                name += usedSets[j].elementName + " ";
            }
        }
        var group = new QueryGroup("Overlap_G_" + i + "_" + parentGroup.id, name, queries[i]);
        group.level = level;
        getSubsetsForMaskList(subSets, [queries[i]], function (d) {
            group.addSubSet(d);
        });
        if (group.subSets.length > 0) {
            newGroups.unshift(group);
        }
    }

    return newGroups;
//    console.log(queries);

//    for (var i = 0; i < subSets.length; i++) {
//        mask = Array.apply(null, new Array(subSets.length)).map(Number.prototype.valueOf, 0);
//        mask[i] = 1;
//    }

}

var fillMasks = function (setMask, length, minSets, queries) {

    var bitMask = 1;

    var query = Array.apply(null, new Array(length)).map(Number.prototype.valueOf, 0);

    var memberCount = 0;

    for (var setIndex = length - 1; setIndex >= 0; setIndex--) {
        if ((setMask & bitMask) === 1) {
            query[setIndex] = 1;
            memberCount++;
        }
        else {
            query[setIndex] = 2;
        }
        setMask = setMask >> 1;
    }
    if (memberCount == minSets) {
        queries.push(query);
    }

//    var resultMasks = [];
//    for (var maskCount = 0; maskCount < length; maskCount++) {
//        for (var i = 0; i < length; i++) {
//            var newMask = masks[maskCount].slice(0);
//
//
//        }
//    }
}

var groupByRelevanceMeasure = function (subSets, level, parentGroup) {
    var newGroups = [];
    newGroups.push(new Group('GROUP_POS_DEV' + parentGroup.id, 'Positive Expected Value', level));
    newGroups.push(new Group('GROUP_NEG_DEV' + parentGroup.id, 'Negative Expected Value', level));
    newGroups.push(new Group(EMPTY_GROUP_ID + parentGroup.id, 'Empty Subset', level));
    for (var i = 0; i < subSets.length; i++) {
        var index = 0
        if (subSets[i].disproportionality > 0) {
            index = 0;
        }
        else if (subSets[i].disproportionality < 0) {
            index = 1;
        }
        else {
            index = 2;
        }
        newGroups[index].addSubSet(subSets[i])
    }
    return newGroups;
}

var groupByIntersectionSize = function (subSets, level, parentGroup) {
    var newGroups = [];
    newGroups.push(new Group(EMPTY_GROUP_ID + parentGroup.id, 'Empty Subset', level));
    var maxSetSize = Math.min(usedSets.length, UpSetState.maxCardinality);
    for (var i = UpSetState.minCardinality; i < maxSetSize; i++) {
        newGroups.push(new Group(SET_SIZE_GROUP_PREFIX + (i + 1) + '_' + parentGroup.id, (i + 1) + '-Set Subsets', level));
    }
    subSets.forEach(function (subSet) {
        var group = newGroups[subSet.nrCombinedSets];
        if (group != null)
            group.addSubSet(subSet);
        else
            console.log('Fail ' + group + subSet.nrCombinedSets);
    })
    return newGroups;
}

/**
 * Creates groups for all sets containing all subsets of this set
 */
var groupBySet = function (subSets, level, parentGroup) {

    // TODO add empty subset

    var newGroups = [];
    newGroups.push(new Group(EMPTY_GROUP_ID, 'Empty Subset', level));
    for (var i = 0; i < usedSets.length; i++) {
        var group = new Group(SET_BASED_GROUPING_PREFIX + (i + 1) + parentGroup.id, usedSets[i].elementName, level);

        newGroups.push(group);

        subSets.forEach(function (subSet) {
            if (subSet.combinedSets[i] !== 0) {
                group.addSubSet(subSet);
            }
        });
    }
    return newGroups;
};

/** Collapse or uncollapse group */
var collapseGroup = function (group) {
    group.isCollapsed = !group.isCollapsed;

    UpSetState.collapseChanged = true;
    updateState();
    return;

};

var collapseAggregate = function (aggregate) {
    aggregate.isCollapsed = !aggregate.isCollapsed;
    updateState();
};

// ----------------------- Sort Functions ----------------------------

/** Filters the provided list of subsets to include only those of length >0. If no list of subsets is provided the global list is used. */
function getFilteredSubSets(subSetsToFilter) {
    if (!subSetsToFilter) {
        subSetsToFilter = subSets;
    }
    if (!UpSetState.hideEmpties) {
        return subSetsToFilter.slice(0);
    }
    var filteredSubSets = []
    for (var i = 0; i < subSetsToFilter.length; i++) {
        if (subSetsToFilter[i].items.length > 0) {
            filteredSubSets.push(subSetsToFilter[i]);
        }
    }
    return filteredSubSets;
}

var sortBySetItem = function (subSets, set) {
    if (!set) {
        set = usedSets[0];
    }
    var dataRows = getFilteredSubSets(subSets);
    var setIndex = usedSets.indexOf(set);
    dataRows.sort(function (a, b) {
        // move all elements that contain the clicked set to the top
        if (b.combinedSets[setIndex] !== a.combinedSets[setIndex]) {
            return b.combinedSets[setIndex] - a.combinedSets[setIndex];
        }
        // move all elements with fewer intersections to the top
        if (a.nrCombinedSets !== b.nrCombinedSets) {
            return a.nrCombinedSets - b.nrCombinedSets;
        }
        // if the number of combined sets is identical, we can pick the largest one
        return b.id - a.id;
    });
    return dataRows;
}

var sortByCombinationSize = function (subSets) {
    var dataRows = getFilteredSubSets(subSets);

// sort by number of combinations
    dataRows.sort(function (a, b) {
        if (a.nrCombinedSets !== b.nrCombinedSets) {
            return a.nrCombinedSets - b.nrCombinedSets;
        }
        // if the number of combined sets is identical, we can pick the largest one
        return b.id - a.id;
    });
    return dataRows;
}

/** sort by size of set overlap */
var sortBySubSetSize = function (subSets) {
    var dataRows = getFilteredSubSets(subSets);
    dataRows.sort(function (a, b) {
        return b.setSize - a.setSize;
    });
    return dataRows;
}

/** sort by size of set overlap */
var sortByExpectedValue = function (subSets) {
    var dataRows = getFilteredSubSets(subSets);

    dataRows.sort(function (a, b) {
        return Math.abs(b.disproportionality) - Math.abs(a.disproportionality);
    });
    return dataRows;
}

/**
 * Takes a list of groups and writes them into an array, according to the nesting & collapse rules
 * @param groupList
 * @returns {*}
 */
var unwrapGroups = function (groupList) {
    var dataRows = []
    for (var i = 0; i < groupList.length; i++) {
        var group = groupList[i];
        // ignoring an empty empty group
        if (group.id === EMPTY_GROUP_ID && group.setSize === 0 || (group.visibleSets.length === 0 && UpSetState.hideEmpties)) {
            continue;
        }
        dataRows.push(group);
        if (UpSetState.collapseAll) {
            group.isCollapsed = true;
        }
        if (UpSetState.expandAll) {
            group.isCollapsed = false;
        }
        if (UpSetState.levelTwoGrouping && group.nestedGroups) {
            dataRows = dataRows.concat(unwrapGroups(group.nestedGroups, []));
            continue;
        }
        if (!group.isCollapsed) {
            dataRows = dataRows.concat(StateMap[UpSetState.sorting](group.visibleSets));

            if (group.aggregate.subSets.length > 0 && !UpSetState.hideEmpties) {
                dataRows.push(group.aggregate);
                if (!group.aggregate.isCollapsed) {
                    for (var k = 0; k < group.aggregate.subSets.length; k++) {
                        dataRows.push(group.aggregate.subSets[k]);
                    }
                }
            }
        }
    }

    return dataRows;
};

var StateMap = {
    groupByIntersectionSize: groupByIntersectionSize,
    groupBySet: groupBySet,
    groupByRelevanceMeasure: groupByRelevanceMeasure,
    groupByOverlapDegree: groupByOverlapDegree,

    sortByCombinationSize: sortByCombinationSize,
    sortBySubSetSize: sortBySubSetSize,
    sortByExpectedValue: sortByExpectedValue,
    sortBySubSetSize: sortBySubSetSize,
    sortBySetItem: sortBySetItem
};

var StateOpt = {
    groupByIntersectionSize: 'groupByIntersectionSize',
    groupBySet: 'groupBySet',
    groupByRelevanceMeasure: 'groupByRelevanceMeasure',
    groupByOverlapDegree: 'groupByOverlapDegree',

    sortByCombinationSize: 'sortByCombinationSize',
    sortBySubSetSize: 'sortBySubSetSize',
    sortByExpectedValue: 'sortByExpectedValue',
    sortBySetItem: 'sortBySetItem'
};

var UpSetState = {
    collapseAll: false,
    expandAll: false,
    // collapseChanged: false,

    grouping: queryParameters["grouping"] || StateOpt.groupBySet,
    levelTwoGrouping: undefined,
    sorting: StateOpt.sortByCombinationSize,

    /** hide empty subsets, groups and aggregates */
    hideEmpties: true,

    /** Sets the upper threshold of cardinality of subsets */
    maxCardinality: undefined,
    /** Sets the lower threshold of cardinality of subsets */
    minCardinality: 0,

    forceUpdate: false,

    /** user defined logic groups **/
    logicGroups: [],
    logicGroupChanged: false

};

var previousState = false;

var updateState = function (parameter) {
    var forceUpdate = !previousState || UpSetState.forceUpdate || (UpSetState.hideEmpties != previousState.hideEmpties);

    // true if pure sorting - no grouping
    if ((UpSetState.sorting && !UpSetState.grouping) && (forceUpdate || (previousState && previousState.sorting !== UpSetState.sorting))) {
        dataRows = StateMap[StateOpt[UpSetState.sorting]](subSets, parameter);
    }
    else if (UpSetState.grouping && (forceUpdate || (previousState && previousState.grouping !== UpSetState.grouping || previousState.levelTwoGrouping !== UpSetState.levelTwoGrouping))) {
        levelOneGroups = StateMap[StateOpt[UpSetState.grouping]](subSets, 1, "");

        if (UpSetState.levelTwoGrouping) {
            levelOneGroups.forEach(function (group) {
                group.nestedGroups = StateMap[StateOpt[UpSetState.levelTwoGrouping]](group.subSets, 2, group);
            });
        }
        dataRows = unwrapGroups(levelOneGroups);

    }
    else if (UpSetState.collapseChanged && UpSetState.grouping) {
        dataRows = unwrapGroups(levelOneGroups);
    }

    if (UpSetState.logicGroupChanged) {
        handleLogicGroups(subSets, 1);
        UpSetState.logicGroupChanged = false;

    }

    if (filterGroups && filterGroups.length > 0) {
        var filteredRows = unwrapGroups(filterGroups);
        var separator = new Separator("FILTER_SEPARATOR", 'Natural Intersections');
        filteredRows.push(separator);
        dataRows = filteredRows.concat(dataRows);
    }

    UpSetState.forceUpdate = false;
    UpSetState.expandAll = false;
    UpSetState.collapseAll = false;
    UpSetState.collapseChanged = false;

    renderRows.length = 0;

    var registry = {};
    var prefix = "";

    var count = 1;
    dataRows.forEach(function (element) {
        var wrapper = {};

        if (UpSetState.grouping === StateOpt.groupBySet || UpSetState.levelTwoGrouping === StateOpt.groupBySet) {
            if (element.type === ROW_TYPE.SUBSET) {
                wrapper.id = prefix + element.id;
            }
            else {
                prefix = element.id + "_";
                wrapper.id = element.id;
            }
        }
        else {

            if (registry.hasOwnProperty(element.id)) {
                count = registry[element.id];
                count += 1;
                registry[element.id] = count;
            }
            else {
                registry[element.id] = 1;
            }

            wrapper.id = element.id + '_' + count;
        }
        wrapper.data = element;
        renderRows.push(wrapper);

    });
    previousState = JSON.parse(JSON.stringify(UpSetState));

    queryParameters["grouping"] = UpSetState.grouping;
    updateQueryParameters();

};
<|endoftext|>


<commit_before>'use strict';
var insp = require('./inspect')

/**
 * Checks the given specifications against the object.
 *
 * When the tests are run the **actual** values are printed to verify visually while
 * each provided specification is validated and a test failure caused if one of them fails.
 *
 * @name spok
 * @function
 * @param {Object} t which has assertion functions `equal` and `deepEqual` (to compare objects) - use
 * **tap**, **tape**, **assert** or any other library that has those and thus is compatible
 * @param {Object} obj the object to verify the specifications against
 * @param {Object} specifications the specifications to verify
 */
module.exports = function spok(t, obj, specifications) {
  var prefix = ''

  function check(k) {
    var specString;
    if (k === '$topic') return;

    var spec = specifications[k]
    var val = obj[k]

    if (typeof spec === 'object') // includes array
      specString = insp(spec, spok.color);
    else
      specString = spec;

    var msg = prefix + k + ' = ' + insp(val, spok.color);

    switch (typeof spec) {
      case 'function': return t.equal(!!spec(val), true, msg);
      case 'boolean':
      case 'number':
      case 'string':
        return t.equal(val, spec, msg)
      case 'object': // includes Array
        return t.deepEqual(val, spec, msg)
      default:
        throw new Error('Type ' + typeof spec + ' not yet handled. Please submit a PR')
    }
  }

  if (specifications.$topic) {
    prefix = specifications.$topic + '.';
    // print indicator that a specific spec started being evaluated
    t.equal(1, 1, 'spok: ' + specifications.$topic)
  }

  // check all specs
  Object.keys(specifications).forEach(check);

  // print confirmation that spec is done
  t.equal(1, 1, 'spokie dokie')
  if (spok.sound) require('child_process').execSync('say spokie dokie -v Vicki -r 600')

}

var spok = module.exports;

spok.sound = false;
spok.color = true;

/**
 * Specififies that the given number is within the given range, i.e. `min<= x <=max`.
 *
 * ```js
 * var spec = {
 *  x: spok.range(1, 2)   // specifies that x should be >=1 and <=2
 * }
 * ```
 *
 * @name spok::range
 * @function
 * @param {Number} min minimum
 * @param {Number} max maximum
 * @return {function} function used by spok to check this condition
 */
spok.range = function range(min, max) {
  return function checkRange(x) {
    return spok.number(x) && min <= x && x <= max;
  }
}

/**
 * Specififies that a number is greater than the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.gt(1)  // specifies that x should be >1
 * }
 * ```
 *
 * @name spok::gt
 * @function
 * @param {Number} n criteria
 */
spok.gt = function gt(n) {
  return function checkgt(x) {
    return spok.number(x) && x > n;
  }
}

/**
 * Specififies that a number is greater or equal the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.ge(1)  // specifies that x should be >=1
 * }
 * ```
 *
 * @name spok::ge
 * @function
 * @param {Number} n criteria
 */
spok.ge = function ge(n) {
  return function checkge(x) {
    return spok.number(x) && x >= n;
  }
}

/**
 * Specififies that a number is less than the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.range(1)  // specifies that x should be < 1
 * }
 * ```
 *
 * @name spok::lt
 * @function
 * @param {Number} n criteria
 */
spok.lt = function lt(n) {
  return function checklt(x) {
    return spok.number(x) && x < n;
  }
}

/**
 * Specififies that a number is less or equal the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.le(1)  // specifies that x should be <=1
 * }
 * ```
 *
 * @name spok::le
 * @function
 * @param {Number} n criteria
 */
spok.le = function le(n) {
  return function checkle(x) {
    return spok.number(x) && x <= n;
  }
}

/**
 * Specifies that the value is not equal another.
 *
 * ```js
 * var spec = {
 *  x: spok.not(undefined)  // specifies that x should be defined
 * }
 * ```
 *
 * @name spok::ne
 * @function
 * @param {Any} value criteria
 */
spok.ne = function ne(value) {
  return function checkne(x) {
    return value !== x
  }
}

/**
 * Specifies that the input is of a given type.
 *
 * ```js
 * var spec = {
 *  x: spok.type('number')  // specifies that x should be a Number
 * }
 * ```
 *
 * @name spok::type
 * @function
 * @param {String} t expected type
 */
spok.type = function type(t) {
  console.error('typeof t: %s', t)
  return function checkType(x) {
    return typeof x === t;
  }
}

/**
 * Specifies that the input is an array.
 *
 * ```js
 * var spec = {
 *  x: spok.array  // specifies that x should be an Array
 * }
 * ```
 *
 * @name spok::array
 * @function
 * @param {Any} x value checked by spok to be an array when the tests run
 * @return {Boolean} `true` if spec is validated otherwise `false`
 */
spok.array = function array(x) {
  return Array.isArray(x)
}

/**
 * Specifies that the input of type number and `isNaN(x)` returns `false`.
 *
 * ```js
 * var spec = {
 *  x: spok.number  // specifies that x should be a Number
 * }
 * ```
 *
 * @name spok::number
 * @function
 * @param {Any} x value checked by spok to be a number the tests run
 * @return {Boolean} `true` if spec is validated otherwise `false`
 */
spok.number = function number(x) {
  return typeof x === 'number' && !isNaN(x)
}

/**
 * Specifies that the input is a string.
 *
 * ```
 * var spec = {
 *   x: spok.string  // specifies that x should be a String
 * }
 * ```
 *
 * @name spok::string
 * @function
 * @return {Boolean} `true` if spec is validated otherwise `false`
 */
spok.string = spok.type('string')

/**
 * Specifies that the input is an object and it is not `null`.
 *
 * ```js
 * var spec = {
 *  x: spok.definedObject  // specifies that x is a non-null object
 * }
 * ```
 *
 * @name spok::definedObject
 * @function
 * @return {Boolean} `true` if spec is validated otherwise `false`
 */
spok.definedObject = function definedObject(x) {
  return x !== null && typeof x === 'object'
}

/**
 * Specifies that the string starts with the specified substring.
 *
 * **NOTE**: only available with io.js which has an ES6 `startsWith` function
 *
 * ```js
 * var spec = {
 *  x: spok.startsWith('hello')  // specifies that x should start with 'hello'
 * }
 * ```
 *
 * @name spok::startsWith
 * @function
 * @param {String} what substring the given string should start with
 */
spok.startsWith = function startsWith(what) {
  return function checkStartsWith(x) {
    var res = x && typeof x.startsWith === 'function' && x.startsWith(what)
    if (!res) console.error('%s !==\n%s', x, what)
    return res
  }
}
<commit_msg>docs: fixes and simplifications<commit_after>'use strict';
var insp = require('./inspect')

/**
 * Checks the given specifications against the object.
 *
 * When the tests are run the **actual** values are printed to verify visually while
 * each provided specification is validated and a test failure caused if one of them fails.
 *
 * @name spok
 * @function
 * @param {Object} t which has assertion functions `equal` and `deepEqual` (to compare objects) - use
 * **tap**, **tape**, **assert** or any other library that has those and thus is compatible
 * @param {Object} obj the object to verify the specifications against
 * @param {Object} specifications the specifications to verify
 */
module.exports = function spok(t, obj, specifications) {
  var prefix = ''

  function check(k) {
    var specString;
    if (k === '$topic') return;

    var spec = specifications[k]
    var val = obj[k]

    if (typeof spec === 'object') // includes array
      specString = insp(spec, spok.color);
    else
      specString = spec;

    var msg = prefix + k + ' = ' + insp(val, spok.color);

    switch (typeof spec) {
      case 'function': return t.equal(!!spec(val), true, msg);
      case 'boolean':
      case 'number':
      case 'string':
        return t.equal(val, spec, msg)
      case 'object': // includes Array
        return t.deepEqual(val, spec, msg)
      default:
        throw new Error('Type ' + typeof spec + ' not yet handled. Please submit a PR')
    }
  }

  if (specifications.$topic) {
    prefix = specifications.$topic + '.';
    // print indicator that a specific spec started being evaluated
    t.equal(1, 1, 'spok: ' + specifications.$topic)
  }

  // check all specs
  Object.keys(specifications).forEach(check);

  // print confirmation that spec is done
  t.equal(1, 1, 'spokie dokie')
  if (spok.sound) require('child_process').execSync('say spokie dokie -v Vicki -r 600')

}

var spok = module.exports;

spok.sound = false;
spok.color = true;

/**
 * Specififies that the given number is within the given range, i.e. `min<= x <=max`.
 *
 * ```js
 * var spec = {
 *  x: spok.range(1, 2)   // specifies that x should be >=1 and <=2
 * }
 * ```
 *
 * @name spok::range
 * @function
 * @param {Number} min minimum
 * @param {Number} max maximum
 */
spok.range = function range(min, max) {
  return function checkRange(x) {
    return spok.number(x) && min <= x && x <= max;
  }
}

/**
 * Specififies that a number is greater than the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.gt(1)  // specifies that x should be >1
 * }
 * ```
 *
 * @name spok::gt
 * @function
 * @param {Number} n criteria
 */
spok.gt = function gt(n) {
  return function checkgt(x) {
    return spok.number(x) && x > n;
  }
}

/**
 * Specififies that a number is greater or equal the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.ge(1)  // specifies that x should be >=1
 * }
 * ```
 *
 * @name spok::ge
 * @function
 * @param {Number} n criteria
 */
spok.ge = function ge(n) {
  return function checkge(x) {
    return spok.number(x) && x >= n;
  }
}

/**
 * Specififies that a number is less than the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.lt(1)  // specifies that x should be < 1
 * }
 * ```
 *
 * @name spok::lt
 * @function
 * @param {Number} n criteria
 */
spok.lt = function lt(n) {
  return function checklt(x) {
    return spok.number(x) && x < n;
  }
}

/**
 * Specififies that a number is less or equal the given criteria.
 *
 * ```js
 * var spec = {
 *  x: spok.le(1)  // specifies that x should be <=1
 * }
 * ```
 *
 * @name spok::le
 * @function
 * @param {Number} n criteria
 */
spok.le = function le(n) {
  return function checkle(x) {
    return spok.number(x) && x <= n;
  }
}

/**
 * Specifies that the value is not equal another.
 *
 * ```js
 * var spec = {
 *  x: spok.ne(undefined)  // specifies that x should be defined
 * }
 * ```
 *
 * @name spok::ne
 * @function
 * @param {Any} value criteria
 */
spok.ne = function ne(value) {
  return function checkne(x) {
    return value !== x
  }
}

/**
 * Specifies that the input is of a given type.
 *
 * ```js
 * var spec = {
 *  x: spok.type('number')  // specifies that x should be a Number
 * }
 * ```
 *
 * @name spok::type
 * @function
 * @param {String} t expected type
 */
spok.type = function type(t) {
  return function checkType(x) {
    return typeof x === t;
  }
}

/**
 * Specifies that the input is an array.
 *
 * ```js
 * var spec = {
 *  x: spok.array  // specifies that x should be an Array
 * }
 * ```
 *
 * @name spok::array
 * @function
 */
spok.array = function array(x) {
  return Array.isArray(x)
}

/**
 * Specifies that the input of type number and `isNaN(x)` returns `false`.
 *
 * ```js
 * var spec = {
 *  x: spok.number  // specifies that x should be a Number
 * }
 * ```
 *
 * @name spok::number
 * @function
 */
spok.number = function number(x) {
  return typeof x === 'number' && !isNaN(x)
}

/**
 * Specifies that the input is a string.
 *
 * ```
 * var spec = {
 *   x: spok.string  // specifies that x should be a String
 * }
 * ```
 *
 * @name spok::string
 * @function
 */
spok.string = spok.type('string')

/**
 * Specifies that the input is an object and it is not `null`.
 *
 * ```js
 * var spec = {
 *  x: spok.definedObject  // specifies that x is a non-null object
 * }
 * ```
 *
 * @name spok::definedObject
 * @function
 */
spok.definedObject = function definedObject(x) {
  return x !== null && typeof x === 'object'
}

/**
 * Specifies that the string starts with the specified substring.
 *
 * **NOTE**: only available with io.js which has an ES6 `startsWith` function
 *
 * ```js
 * var spec = {
 *  x: spok.startsWith('hello')  // specifies that x should start with 'hello'
 * }
 * ```
 *
 * @name spok::startsWith
 * @function
 * @param {String} what substring the given string should start with
 */
spok.startsWith = function startsWith(what) {
  return function checkStartsWith(x) {
    var res = x && typeof x.startsWith === 'function' && x.startsWith(what)
    if (!res) console.error('%s !==\n%s', x, what)
    return res
  }
}
<|endoftext|>