<commit_before>define([
    "dojo/ready",
    "dojo/_base/declare",
    "dojo/_base/lang",
    "esri/arcgis/utils",
    "esri/IdentityManager"
],
function(
    ready,
    declare,
    lang,
    arcgisUtils,
    IdentityManager
) {
    return declare("", null, {
        config: {},
        constructor: function(config) {
            //config will contain application and user defined info for the template such as i18n strings, the web map id
            // and application id
            // any url parameters and any application specific configuration information.
            this.config = config;
            ready(lang.hitch(this, function() {
                this._createWebMap();
            }));
        },
        _mapLoaded: function() {
            // Map is ready
            console.log('map loaded');
        },
        //create a map based on the input web map id
        _createWebMap: function() {
            arcgisUtils.createMap(this.config.webmap, "mapDiv", {
                mapOptions: {
                    //Optionally define additional map config here for example you can
                    //turn the slider off, display info windows, disable wraparound 180, slider position and more.
                },
                bingMapsKey: this.config.bingmapskey
            }).then(lang.hitch(this, function(response) {
                //Once the map is created we get access to the response which provides important info
                //such as the map, operational layers, popup info and more. This object will also contain
                //any custom options you defined for the template. In this example that is the 'theme' property.
                //Here' we'll use it to update the application to match the specified color theme.
                console.log(this.config);
                this.map = response.map;
                if (this.map.loaded) {
                    // do something with the map
                    this._mapLoaded();
                } else {
                    on(this.map, "load", lang.hitch(this, function() {
                        // do something with the map
                        this._mapLoaded();
                    }));
                }
            }), lang.hitch(this, function(error) {
                //an error occurred - notify the user. In this example we pull the string from the
                //resource.js file located in the nls folder because we've set the application up
                //for localization. If you don't need to support mulitple languages you can hardcode the
                //strings here and comment out the call in index.html to get the localization strings.
                if (this.config && this.config.i18n) {
                    alert(this.config.i18n.map.error + ": " + error.message);
                } else {
                    alert("Unable to create map: " + error.message);
                }
            }));
        }
    });
});<commit_msg>fixes #9<commit_after>define([
    "dojo/ready",
    "dojo/_base/declare",
    "dojo/_base/lang",
    "esri/arcgis/utils",
    "esri/IdentityManager",
    "dojo/on"
],
function(
    ready,
    declare,
    lang,
    arcgisUtils,
    IdentityManager,
    on
) {
    return declare("", null, {
        config: {},
        constructor: function(config) {
            //config will contain application and user defined info for the template such as i18n strings, the web map id
            // and application id
            // any url parameters and any application specific configuration information.
            this.config = config;
            ready(lang.hitch(this, function() {
                this._createWebMap();
            }));
        },
        _mapLoaded: function() {
            // Map is ready
            console.log('map loaded');
        },
        //create a map based on the input web map id
        _createWebMap: function() {
            arcgisUtils.createMap(this.config.webmap, "mapDiv", {
                mapOptions: {
                    //Optionally define additional map config here for example you can
                    //turn the slider off, display info windows, disable wraparound 180, slider position and more.
                },
                bingMapsKey: this.config.bingmapskey
            }).then(lang.hitch(this, function(response) {
                //Once the map is created we get access to the response which provides important info
                //such as the map, operational layers, popup info and more. This object will also contain
                //any custom options you defined for the template. In this example that is the 'theme' property.
                //Here' we'll use it to update the application to match the specified color theme.
                console.log(this.config);
                this.map = response.map;
                if (this.map.loaded) {
                    // do something with the map
                    this._mapLoaded();
                } else {
                    on.once(this.map, "load", lang.hitch(this, function() {
                        // do something with the map
                        this._mapLoaded();
                    }));
                }
            }), lang.hitch(this, function(error) {
                //an error occurred - notify the user. In this example we pull the string from the
                //resource.js file located in the nls folder because we've set the application up
                //for localization. If you don't need to support mulitple languages you can hardcode the
                //strings here and comment out the call in index.html to get the localization strings.
                if (this.config && this.config.i18n) {
                    alert(this.config.i18n.map.error + ": " + error.message);
                } else {
                    alert("Unable to create map: " + error.message);
                }
            }));
        }
    });
});<|endoftext|>


<commit_before>import Ember from 'ember';
import { EKMixin, keyDown } from 'ember-keyboard';
const {
  on,
  Mixin,
  computed,
} = Ember;

export default Mixin.create(EKMixin, {
  dropdownOpen: computed.alias('dropdownController.isOpen'),
  keyboardActivated: computed.alias('dropdownOpen'),
  keyboardFirstResponder: computed.alias('dropdownOpen'),
  cancelSelected: true,
  applySelected: false,

  _returnHandler: on(keyDown('Enter'), function() {
    this.onTriggerReturn();
  }),

  _escapeHandler: on(keyDown('Escape'), function() {
    this.onTriggerEscape();
  }),

  _leftArrowHandler: on(keyDown('ArrowLeft'), function() {
    this.onTriggerArrowUp();
  }),

  _rightArrowHandler: on(keyDown('ArrowRight'), function() {
    this.onTriggerArrowDown();
  }),

  _downArrowHandler: on(keyDown('ArrowDown'), function() {
    this.onTriggerArrowDown();
  }),

  _upArrowHandler: on(keyDown('ArrowUp'), function() {
    this.onTriggerArrowUp();
  }),

  toggleSelection() {
    this.toggleProperty('cancelSelected');
    this.toggleProperty('applySelected');
  },

  onTriggerArrowDown() {
    this.toggleSelection();
  },

  onTriggerArrowUp() {
    this.toggleSelection();
  },

  onTriggerEscape() {
    this.send('cancel');
  },

  onTriggerReturn() {
    if (this.get('dropdownOpen')) {
      if (!this.get('datesSame')) {
        if (this.get('cancelSelected')) {
          this.send('cancel');
        } else {
          this.send('apply');
        }
      }
    } else {
      this.get('dropdownController').actions.toggle();
    }
  },
});
<commit_msg>Select Text on Close<commit_after>import Ember from 'ember';
import { EKMixin, keyDown } from 'ember-keyboard';
const {
  on,
  Mixin,
  computed,
} = Ember;

export default Mixin.create(EKMixin, {
  dropdownOpen: computed.alias('dropdownController.isOpen'),
  keyboardActivated: computed.alias('dropdownOpen'),
  keyboardFirstResponder: computed.alias('dropdownOpen'),
  cancelSelected: true,
  applySelected: false,

  _returnHandler: on(keyDown('Enter'), function() {
    this.onTriggerReturn();
  }),

  _escapeHandler: on(keyDown('Escape'), function() {
    this.onTriggerEscape();
  }),

  _leftArrowHandler: on(keyDown('ArrowLeft'), function() {
    this.onTriggerArrowUp();
  }),

  _rightArrowHandler: on(keyDown('ArrowRight'), function() {
    this.onTriggerArrowDown();
  }),

  _downArrowHandler: on(keyDown('ArrowDown'), function() {
    this.onTriggerArrowDown();
  }),

  _upArrowHandler: on(keyDown('ArrowUp'), function() {
    this.onTriggerArrowUp();
  }),

  toggleSelection() {
    this.toggleProperty('cancelSelected');
    this.toggleProperty('applySelected');
  },

  onTriggerArrowDown() {
    this.toggleSelection();
  },

  onTriggerArrowUp() {
    this.toggleSelection();
  },

  onTriggerEscape() {
    this.send('cancel');
  },

  onTriggerReturn() {
    if (this.get('dropdownOpen')) {
      if (!this.get('datesSame')) {
        if (this.get('cancelSelected')) {
          this.send('cancel');
        } else {
          this.send('apply');
        }
      }
    } else {
      this.get('dropdownController').actions.toggle();
      if (this.get('dropdownOpen')) {
        let element = document.querySelector("." + this.get('topClass') + " .dp-date-input");
        this.$(element).focus();
        this.$(element).select();
      }
    }
  },
});
<|endoftext|>


<commit_before>import { List } from 'immutable';
import { PLAY_CARD } from './hand';

const MAX_CARDS_ON_BOARD = 7;
const initialState = new List;

export default function boardReducer(state = initialState, action) {
  switch (action.type) {
    case PLAY_CARD:
      return state.insert(action.boardIndex, action.card);
    default:
      return state;
  }
}
<commit_msg>Turn off MAX_CARDS_ON_BOARD for now<commit_after>import { List } from 'immutable';
import { PLAY_CARD } from './hand';

// const MAX_CARDS_ON_BOARD = 7;
const initialState = new List;

export default function boardReducer(state = initialState, action) {
  switch (action.type) {
    case PLAY_CARD:
      return state.insert(action.boardIndex, action.card);
    default:
      return state;
  }
}
<|endoftext|>


<commit_before>
// hide the form if the browser doesn't do SVG,
// (then just let everything else fail)
if (!document.createElementNS) {
    document.getElementsByTagName("form")[0].style.display = "none";
}

var percent = (function() {
            var fmt = d3.format(".2f");
            return function(n) { return fmt(n) + "%"; };
        })();

var years = [1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2020,2025,2030,2035,2040],
    fields = [
//            {name: "(no scale)", id: "none"},
           {name: "Primary Energy Consumption (Quadrillion BTU)", id: "PECons", key: "PECons%d", years: years}
//            {name: "Population", id: "num_articles2001", key: "num_articles2001", format: "+,"},
//            {name: "% FB users", id: "p_fb_users", key: "p_fb_users", format: percent},
            // {name: "% of Articles", id: "p_int_users", key: "p_int_users", format: percent},
//            {name: "% Internet users", id: "p_int_users", key: "p_int_users", format: percent},
//            {name: "% FB users of Internet Users", id: "p_fb_users_of_int_users", key: "p_fb_users_of_int_users", format: percent}
        ],

      field = fields[0],
      year = years[0],
      mycolor = ['#deebf7','#9ecae1','#3182bd'],
      colors = mycolor.map(function(rgb) { return d3.hsl(rgb); });

d3.select("input[type=range]").on("change", function() { year = this.value; update(); });
d3.select("input[type=range]").on("click", function() { clearInterval(intervalId); });

var formatter = d3.format("2f");
var tickFormatter = function(d) {
    return formatter(d);
}

//var slider = d3.slider().min(1971).max(2040).ticks(10).showRange(true).tickFormat(tickFormatter).tickValues(["1980","1990","2000","2010","2020","2030","2040"]);

//d3.select("#slider").call(slider);

//d3.select('#slider').on("change", function() { year = this.value; update(); });
//d3.select('#slider').on("click", function() { clearInterval(intervalId); });

//d3.select("#slider").call(d3.slider().axis(true).min(1971).max(2040).step(1).on("slide",function(year = this.value;update();clearInterval(intervalId);)));
//d3.select('#slider').call(d3.slider().axis(true).min(1973).max(2040).ticks(10).showRange(true).value(1973).tickValues(["1980","1990","2000","2010","2020","2030","2040"])
//    .on("change", function() { year = this.value; update(); }));

//d3.select('#slider').on("click", function() { clearInterval(intervalId); });

var intervalId = setInterval(function(){
    if (year < 2012){
        year = year+1;
        update();
    }else if (year == 2012){
        year = year+8;
        update();
    }else if ((year >= 2020) && (year < 2040)){
        year = year+5;
        update();
    }else{
        setInterval(intervalId);
    }
})

var map = d3.select("#map"),
        zoom = d3.behavior.zoom()
                .translate([-114, 32])
                .scale(1.5)
                .scaleExtent([0.5, 10.0])
                .on("zoom", updateZoom),
        layer = map.append("g")
                .attr("id", "layer"),
        countries = layer.append("g")
                .attr("id", "countries")
                .selectAll("path");

// map.call(zoom);
updateZoom();

function updateZoom() {
    var scale = zoom.scale();
    layer.attr("transform",
            "translate(" + zoom.translate() + ") " +
                    "scale(" + [scale, scale] + ")");
}

var proj = d3.geo.eckert3(),
        topology,
        geometries,
        rawData,
        dataById = {},
        carto = d3.cartogram()
                .projection(proj)
                .properties(function(d) {
                    if (d.id in dataById) {
                        return dataById[d.id];
                    } else {
                        var tmp = d3.keys(dataById[d3.keys(dataById)[0]]);
                        var ret = {"numcode": d.id};
                        tmp.forEach(function(i){ret[i] = 0});
                        return ret;
                    }
                })
                .value(function(d) {
                    return +d.properties[field];
                });

var segmentized = location.search === "?segmentized",
        url = ["data",
            segmentized ? "world-segmentized.topojson" : "world-110m_withoutAntarctica.json"
        ].join("/");
d3.json(url, function(topo) {
    topology = topo;
    geometries = topology.objects.countries.geometries;
    d3.csv("data/Energy_Consumption_Countries_20151201.csv", function(data) {
        rawData = data;
        dataById = d3.nest()
                .key(function(d) { return d.numcode; })
                .rollup(function(d) { return d[0]; })
                .map(data);
        init();
    });
});

function init() {
    var features = carto.features(topology, geometries),
            path = d3.geo.path()
                    .projection(proj);

    countries = countries.data(features)
            .enter()
            .append("path")
            .attr("class", "country")
            .attr("id", function(d) {
                return d.id;
            })
            .attr("name", function(d) {
                return d.properties.country;
            })
            .attr("fill", "#fafafa")
            .attr("d", path);

    countries.append("title");

}

function update() {
   // var start = Date.now();

    var key = field.key.replace("%d", year),
            fmt = (typeof field.format === "function")
                    ? field.format
                    : d3.format(field.format || ","),
            value = function(d) {
                return +d.properties[key];
            },
            values = countries.data()
                    .map(value)
                    .filter(function(n) {
                        return !isNaN(n);
                    })
                    .sort(d3.ascending),
            lo = values[0],
            hi = values[values.length - 1];

    var color = d3.scale.linear()
            .range(colors)
            .domain(lo < 0
                    ? [lo, 0, hi]
                   : [lo, d3.mean(values), hi]);

    // normalize the scale to positive numbers
    var scale = d3.scale.linear()
            .domain([lo, hi])
            .range([1, 1000]);

    // tell the cartogram to use the scaled values
    carto.value(function(d) {
        return scale(value(d));
    });

    // generate the new features, pre-projected
    var features = carto(topology, geometries).features;

    // update the data
    countries.data(features)
            .select("title")
            .text(function(d) {
                return [d.properties.country, fmt(value(d))].join(": ");
            });

    countries.transition()
            .duration(500)
            .ease("linear")
            .attr("fill", function(d) {
                return color(value(d));
            })
            .attr("d", carto.path);

    d3.select("input[type=range]")[0][0].value=year;
    d3.select("#theyear > span")[0][0].innerHTML=year;

    //d3.select("#slider")[0][0].value = year;
};
<commit_msg>Update mycartogram.js<commit_after>
// hide the form if the browser doesn't do SVG,
// (then just let everything else fail)
if (!document.createElementNS) {
    document.getElementsByTagName("form")[0].style.display = "none";
}

var percent = (function() {
            var fmt = d3.format(".2f");
            return function(n) { return fmt(n) + "%"; };
        })();

var years = [1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2020,2025,2030,2035,2040],
    fields = [
//            {name: "(no scale)", id: "none"},
           {name: "Primary Energy Consumption (Quadrillion BTU)", id: "PECons", key: "PECons%d", years: years}
//            {name: "Population", id: "num_articles2001", key: "num_articles2001", format: "+,"},
//            {name: "% FB users", id: "p_fb_users", key: "p_fb_users", format: percent},
            // {name: "% of Articles", id: "p_int_users", key: "p_int_users", format: percent},
//            {name: "% Internet users", id: "p_int_users", key: "p_int_users", format: percent},
//            {name: "% FB users of Internet Users", id: "p_fb_users_of_int_users", key: "p_fb_users_of_int_users", format: percent}
        ],

      field = fields[0],
      year = years[0],
      mycolor = ['#deebf7','#9ecae1','#3182bd'],
      colors = mycolor.map(function(rgb) { return d3.hsl(rgb); });

d3.select("input[type=range]").on("change", function() { year = this.value; update(); });
d3.select("input[type=range]").on("click", function() { clearInterval(intervalId); });

var formatter = d3.format("2f");
var tickFormatter = function(d) {
    return formatter(d);
}

//var slider = d3.slider().min(1971).max(2040).ticks(10).showRange(true).tickFormat(tickFormatter).tickValues(["1980","1990","2000","2010","2020","2030","2040"]);

//d3.select("#slider").call(slider);

//d3.select('#slider').on("change", function() { year = this.value; update(); });
//d3.select('#slider').on("click", function() { clearInterval(intervalId); });

//d3.select("#slider").call(d3.slider().axis(true).min(1971).max(2040).step(1).on("slide",function(year = this.value;update();clearInterval(intervalId);)));
//d3.select('#slider').call(d3.slider().axis(true).min(1973).max(2040).ticks(10).showRange(true).value(1973).tickValues(["1980","1990","2000","2010","2020","2030","2040"])
//    .on("change", function() { year = this.value; update(); }));

//d3.select('#slider').on("click", function() { clearInterval(intervalId); });

var intervalId = setInterval(function(){
    if (year < 2012){
        year = year+1;
        update();
    }else if (year == 2012){
        year = year+8;
        update();
    }else if ((year >= 2020) && (year < 2040)){
        year = year+5;
        update();
    }else{
        setInterval(intervalId);
    }
})

var map = d3.select("#map"),
        zoom = d3.behavior.zoom()
                .translate([-228, 32])
                .scale(2)
                .scaleExtent([0.5, 10.0])
                .on("zoom", updateZoom),
        layer = map.append("g")
                .attr("id", "layer"),
        countries = layer.append("g")
                .attr("id", "countries")
                .selectAll("path");

// map.call(zoom);
updateZoom();

function updateZoom() {
    var scale = zoom.scale();
    layer.attr("transform",
            "translate(" + zoom.translate() + ") " +
                    "scale(" + [scale, scale] + ")");
}

var proj = d3.geo.eckert3(),
        topology,
        geometries,
        rawData,
        dataById = {},
        carto = d3.cartogram()
                .projection(proj)
                .properties(function(d) {
                    if (d.id in dataById) {
                        return dataById[d.id];
                    } else {
                        var tmp = d3.keys(dataById[d3.keys(dataById)[0]]);
                        var ret = {"numcode": d.id};
                        tmp.forEach(function(i){ret[i] = 0});
                        return ret;
                    }
                })
                .value(function(d) {
                    return +d.properties[field];
                });

var segmentized = location.search === "?segmentized",
        url = ["data",
            segmentized ? "world-segmentized.topojson" : "world-110m_withoutAntarctica.json"
        ].join("/");
d3.json(url, function(topo) {
    topology = topo;
    geometries = topology.objects.countries.geometries;
    d3.csv("data/Energy_Consumption_Countries_20151201.csv", function(data) {
        rawData = data;
        dataById = d3.nest()
                .key(function(d) { return d.numcode; })
                .rollup(function(d) { return d[0]; })
                .map(data);
        init();
    });
});

function init() {
    var features = carto.features(topology, geometries),
            path = d3.geo.path()
                    .projection(proj);

    countries = countries.data(features)
            .enter()
            .append("path")
            .attr("class", "country")
            .attr("id", function(d) {
                return d.id;
            })
            .attr("name", function(d) {
                return d.properties.country;
            })
            .attr("fill", "#fafafa")
            .attr("d", path);

    countries.append("title");

}

function update() {
   // var start = Date.now();

    var key = field.key.replace("%d", year),
            fmt = (typeof field.format === "function")
                    ? field.format
                    : d3.format(field.format || ","),
            value = function(d) {
                return +d.properties[key];
            },
            values = countries.data()
                    .map(value)
                    .filter(function(n) {
                        return !isNaN(n);
                    })
                    .sort(d3.ascending),
            lo = values[0],
            hi = values[values.length - 1];

    var color = d3.scale.linear()
            .range(colors)
            .domain(lo < 0
                    ? [lo, 0, hi]
                   : [lo, d3.mean(values), hi]);

    // normalize the scale to positive numbers
    var scale = d3.scale.linear()
            .domain([lo, hi])
            .range([1, 1000]);

    // tell the cartogram to use the scaled values
    carto.value(function(d) {
        return scale(value(d));
    });

    // generate the new features, pre-projected
    var features = carto(topology, geometries).features;

    // update the data
    countries.data(features)
            .select("title")
            .text(function(d) {
                return [d.properties.country, fmt(value(d))].join(": ");
            });

    countries.transition()
            .duration(500)
            .ease("linear")
            .attr("fill", function(d) {
                return color(value(d));
            })
            .attr("d", carto.path);

    d3.select("input[type=range]")[0][0].value=year;
    d3.select("#theyear > span")[0][0].innerHTML=year;

    //d3.select("#slider")[0][0].value = year;
};
<|endoftext|>


<commit_before>setTimeout(function(){console.log("Hooking up!"),$(function(){function c(){var a=$('#starred-posts .collapsible a[href$=".gif"],#starred-posts .collapsible a[href$=".jpeg"],#starred-posts .collapsible a[href$=".jpg"],#starred-posts .collapsible a[href$=".png"]');a=a.filter(":not(.thumbified)"),a.each(function(){var a=$("",{src:this.href,class:"hoverable"});$(this).addClass("thumbified").append(a)})}var a=$('clear | remove media | ');$("#sidebar-menu").prepend(a),$("#soc_clr").click(function(a){a.preventDefault(),$("div.monologue, div.system-message").remove()}),$("#soc_wipeimg").click(function(a){a.preventDefault(),$("div.ob-image > a").addClass("deleted").text("(Image removed)"),$("div.ob-youtube > a").addClass("deleted").text("(Video removed)"),$("div.monologue .messages:contains('▒')").text("(Silly ASCII art removed)")});var b=document.createElement("style");rules=".hoverable {   display: none;   position: absolute;   z-index: 1;   left: -142px;   bottom: -1px;   border: 4px solid white;   width: 128px;   box-shadow: 0 0 3px rgba(0,0,0,0.85);} a:hover .hoverable {   display: block;}",b.styleSheet?b.styleSheet.cssText=rules:b.appendChild(document.createTextNode(rules)),document.head.appendChild(b),new MutationObserver(function(a){c()}).observe($("#starred-posts .collapsible").get(0),{childList:!0,subtree:!0}),c()})},1e3);
<commit_msg>Cleanup<commit_after><|endoftext|>


<commit_before>/**
 *  Copyright (C) 2017 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(() => {
	"use strict";

	const mongoose = require("mongoose");
	const schema = mongoose.Schema({
		_id: false,
		user: String,
		permissions: [String]
	});
	const responseCodes = require('../response_codes.js');
	const C = require('../constants');
	const _ = require('lodash');
	const Project = require('./project');

	const methods = {
		init(user, permissions) {

			this.user = user;
			this.permissions = permissions;
			return this;
		},

		findByUser(user){
			return this.permissions.find(perm => perm.user === user);
		},

		_check(user, permission){

			if(!this.user.customData.billing.subscriptions.findByAssignedUser(user)){
				return Promise.reject(responseCodes.USER_NOT_ASSIGNED_WITH_LICENSE);
			}

			const isPermissionInvalid = permission.permissions &&
				_.intersection(permission.permissions, C.ACCOUNT_PERM_LIST).length !== permission.permissions.length;

			if (isPermissionInvalid) {
				return Promise.reject(responseCodes.INVALID_PERM);
			}

			return Promise.resolve();

		},

		add(permission){

			return this._check(permission.user, permission).then(() => {

				if(this.findByUser(permission.user)){
					//return Promise.reject(responseCodes.DUP_ACCOUNT_PERM);
					return this.update(permission.user, permission)
				}
				if(permission.permissions.length === 0)
				{
					//Adding a user with empty permissions is not allowed
					return Promise.reject(responseCodes.ACCOUNT_PERM_EMPTY);
				}

				this.permissions.push(permission);
				return this.user.save().then(() => permission);

			});
		},

		update(user, permission){
			console.log("update function");
			return this._check(user, permission).then(() => {
				console.log("checked.", permission.permissions);
				if(permission && permission.permissions.length === 0)
				{
					//this is actually a remove
					console.log("permissions length is 0");
					return this.remove(permission.user);
				}
				else
				{
					const currPermission = this.findByUser(user);
					console.log(currPermission);

					if(currPermission){
						console.log("valid permissions, overwriting");
						currPermission.permissions = permission.permissions;
						return this.user.save().then(() => permission);
					} else {
						console.log("currPermission is null...", currPermission);
						return Promise.reject(responseCodes.ACCOUNT_PERM_NOT_FOUND);
					}
				}

			});
		},

		remove(user){

			let index = -1;

			this.permissions.find((perm, i) => {
				if(perm.user === user){
					index = i;
					return true;
				}
			});

			if (index === -1) {
				return Promise.reject(responseCodes.ACCOUNT_PERM_NOT_FOUND);
			} else {
				this.permissions.splice(index, 1);
				return this.user.save().then(() => {
					// remove all project permissions in this project as well, if any
					return Project.find({ account: this.user.user },{ 'permissions.user': user} );
				}).then(projects => {
					return Promise.all(
						projects.map(proj => proj.updateAttrs({
							permissions: proj.permissions.filter(perm => perm.user !== user)
						}))
					);
				}).then(() => this.user);

			}

		}
	};

	// Mongoose doesn't support subschema static method
	module.exports = {
		schema, methods
	};

})();
<commit_msg>ISSUE #445<commit_after>/**
 *  Copyright (C) 2017 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(() => {
	"use strict";

	const mongoose = require("mongoose");
	const schema = mongoose.Schema({
		_id: false,
		user: String,
		permissions: [String]
	});
	const responseCodes = require('../response_codes.js');
	const C = require('../constants');
	const _ = require('lodash');
	const Project = require('./project');

	const methods = {
		init(user, permissions) {

			this.user = user;
			this.permissions = permissions;
			return this;
		},

		findByUser(user){
			return this.permissions.find(perm => perm.user === user);
		},

		_check(user, permission){

			if(!this.user.customData.billing.subscriptions.findByAssignedUser(user)){
				return Promise.reject(responseCodes.USER_NOT_ASSIGNED_WITH_LICENSE);
			}

			const isPermissionInvalid = permission.permissions &&
				_.intersection(permission.permissions, C.ACCOUNT_PERM_LIST).length !== permission.permissions.length;

			if (isPermissionInvalid) {
				return Promise.reject(responseCodes.INVALID_PERM);
			}

			return Promise.resolve();

		},

		add(permission){

			return this._check(permission.user, permission).then(() => {

				if(this.findByUser(permission.user)){
					//return Promise.reject(responseCodes.DUP_ACCOUNT_PERM);
					return this.update(permission.user, permission)
				}
				if(permission.permissions.length === 0)
				{
					//Adding a user with empty permissions is not allowed
					return Promise.reject(responseCodes.ACCOUNT_PERM_EMPTY);
				}

				this.permissions.push(permission);
				return this.user.save().then(() => permission);

			});
		},

		update(user, permission){
			console.log("update function");
			return this._check(user, permission).then(() => {
				console.log("checked.", permission.permissions);
				if(permission && permission.permissions.length === 0)
				{
					//this is actually a remove
					console.log("permissions length is 0");
					return this.remove(permission.user);
				}
				else
				{
					const currPermission = this.findByUser(user);
					console.log(currPermission);

					if(currPermission){
						console.log("valid permissions, overwriting");
						currPermission.permissions = permission.permissions;
						return this.user.save().then(() => permission);
					} else {
						console.log("currPermission is null...", currPermission);
						return Promise.reject(responseCodes.ACCOUNT_PERM_NOT_FOUND);
					}
				}

			});
		},

		remove(user){
			console.log("removing user", perm);
			console.log(permissions);
			let index = -1;

			this.permissions.find((perm, i) => {
				if(perm.user === user){
					index = i;
					return true;
				}
			});

			if (index === -1) {
				return Promise.reject(responseCodes.ACCOUNT_PERM_NOT_FOUND);
			} else {
				this.permissions.splice(index, 1);
				return this.user.save().then(() => {
					// remove all project permissions in this project as well, if any
					return Project.find({ account: this.user.user },{ 'permissions.user': user} );
				}).then(projects => {
					return Promise.all(
						projects.map(proj => proj.updateAttrs({
							permissions: proj.permissions.filter(perm => perm.user !== user)
						}))
					);
				}).then(() => this.user);

			}

		}
	};

	// Mongoose doesn't support subschema static method
	module.exports = {
		schema, methods
	};

})();
<|endoftext|>


<commit_before>export default {
  init() {
    function logger(printMe) {
      const i = this.index.log;
      this.index.log += 1;
      let nowTime = new Date();
      nowTime = `${nowTime.getMinutes()}.${nowTime.getSeconds()}`;
      const prefix = `## Captain's log, stardate ${i}:${nowTime} ->`;
      if (printMe) {
        console.log(`${prefix} ${printMe} ##`);
      } else {
        console.log(`${prefix} Space is vast and empty (-__-) ##`);
      }
    }

    class ChimneyStack {
      constructor() {
        this.index = { log: 0, brick: 1 };
        this.append = [];
        this.pattern = { open: ['b', 's'], repeat: ['s', 'b'] };
        this.brickSizes = { b: 'big_brick', s: 'small_brick' };
        this.$articles = $('main').children('article');
      }
      elementCreator(template) {
        const newbie = document.createElement('div');
        newbie.setAttribute('class', this.brickSizes[template]);
        newbie.setAttribute('aria-hidden', 'true');
        return newbie;
      }
      usePattern(key) {
        for (const current of this.pattern[key]) {
          const newbie = (key === 'open') || (this.$articles.length === 0) ?
            this.elementCreator(current) : this.factory(current);
          this.append.push(newbie);
        }
      }
      factory(element) {
        const kiln = {
          virgin: this.index.brick,
          full: () => {
            const newbie = this.$articles.eq(0);
            this.$articles = this.$articles.splice(0, 1);
            this.index.brick = 0;
            return newbie;
          },
          hollow: () => this.elementCreator(element),
        };
        return (((element === 'b') && (Math.random() > 0.3)) || !kiln.virgin ?
          kiln.full() : kiln.hollow()
        );
      }
    }

    const chim = new ChimneyStack();
    logger.call(chim, chim.usePattern('open'));

    /* THE PLAN

YES      create template empty elements, big (Be) and small (Ba)
YES      find articles, store number
YES      enable debugging and test articles have been found
NA      pattern now = BaBaBaBaBa...n(articles)
YES      Create pattern ref = SeBa,BoSe,SeBo,BoSe
YES      Create new object, Store BeSe then begin adding elements according to the pattern,
YES      If element is Bo, .33 probability of becoming Ba,
YES      If element is Ba, use next article instead of template element
    */
  },
  finalize() {
    // JavaScript to be fired on the home page, after the init JS
  },
};
<commit_msg>Logging script encapsulated<commit_after>export default {
  init() {
    class Logger {
      static log(printMe) {
        this.log = !this.log ? 1 : this.log += 1;
        let nowTime = new Date();
        nowTime = `${nowTime.getMinutes()}.${nowTime.getSeconds()}`;
        const prefix = `## Captain's log, stardate ${this.log}:${nowTime} ->`;
        if (printMe) {
          console.log(`${prefix} ${printMe} ##`);
        } else {
          console.log(`${prefix} Space is vast and empty (-__-) ##`);
        }
      }
    }

    class ChimneyStack {
      constructor() {
        this.index = { brick: 1 };
        this.append = [];
        this.pattern = { open: ['b', 's'], repeat: ['s', 'b'] };
        this.brickSizes = { b: 'big_brick', s: 'small_brick' };
        this.$articles = $('main').children('article');
      }
      elementCreator(template) {
        const newbie = document.createElement('div');
        newbie.setAttribute('class', this.brickSizes[template]);
        newbie.setAttribute('aria-hidden', 'true');
        return newbie;
      }
      usePattern(key) {
        for (const current of this.pattern[key]) {
          const newbie = (key === 'open') || (this.$articles.length === 0) ?
            this.elementCreator(current) : this.factory(current);
          this.append.push(newbie);
        }
      }
      factory(element) {
        const kiln = {
          virgin: this.index.brick,
          full: () => {
            const newbie = this.$articles.eq(0);
            this.index.brick = 0;
            if (newbie.length === 1) {
              this.$articles = this.$articles.splice(0, 1);
              return newbie;
            }
            return kiln.hollow();
          },
          hollow: () => this.elementCreator(element),
        };
        return (((element === 'b') && (Math.random() > 0.3)) || kiln.virgin ?
          kiln.full() : kiln.hollow()
        );
      }
    }

    const chim = new ChimneyStack();
    Logger.log(chim.usePattern('open'));

    /* THE PLAN

YES      create template empty elements, big (Be) and small (Ba)
YES      find articles, store number
YES      enable debugging and test articles have been found
NA      pattern now = BaBaBaBaBa...n(articles)
YES      Create pattern ref = SeBa,BoSe,SeBo,BoSe
YES      Create new object, Store BeSe then begin adding elements according to the pattern,
YES      If element is Bo, .33 probability of becoming Ba,
YES      If element is Ba, use next article instead of template element
    */
  },
  finalize() {
    // JavaScript to be fired on the home page, after the init JS
  },
};
<|endoftext|>


<commit_before>/**
 * @module ember-paper
 */
import Ember from 'ember';

const { Mixin, computed, A, assert, isArray, Logger, get, String: { loc }, isBlank } = Ember;

import requiredValidator from 'ember-paper/validators/required';
import minValidator from 'ember-paper/validators/min';
import maxValidator from 'ember-paper/validators/max';
import minlengthValidator from 'ember-paper/validators/minlength';
import maxlengthValidator from 'ember-paper/validators/maxlength';

/**
 * In order to make validation generic it is required that components using the validation mixin
 * specify what property the validation logic should be based on.
 *
 * @public
 *
 * @return computed property that depends on the supplied property name
 */
function buildComputedValidationMessages(property, validations = [], customValidations = []) {
  let validationParams = validations.map((v) => get(v, 'param')).filter((v) => !isBlank(v));
  let customValidationParams = customValidations.map((v) => get(v, 'param')).filter((v) => !isBlank(v));

  return computed(property, 'errors.[]', 'customValidations.[]', ...validationParams, ...customValidationParams, function() {
    let validations = A();
    let messages = A();

    // built-in validations
    validations.pushObjects(this.validations());

    // custom validations
    let customValidations = this.get('customValidations');
    assert('`customValidations` must be an array', isArray(customValidations));
    validations.pushObjects(customValidations);

    // execute validations
    let currentValue = this.get(property);
    validations.forEach((validation) => {
      assert('validation must include an `validate(value)` function', validation && validation.validate && typeof validation.validate === 'function');
      try {
        let valParam = get(validation, 'param');
        let paramValue = valParam ? this.get(valParam) : undefined;
        if (!validation.validate(currentValue, paramValue)) {
          let message = this.get(`errorMessages.${valParam}`) || get(validation, 'message');
          messages.pushObject({
            message: loc(message.string || message, paramValue, currentValue)
          });
        }
      } catch(error) {
        Logger.error('Exception with validation: ', validation, error);
      }
    });

    // error messages array
    let errors = this.get('errors') || [];
    assert('`errors` must be an array', isArray(errors));
    messages.pushObjects(errors.map((e) => {
      return get(e, 'message') ? e : { message: e };
    }));

    return messages;
  });
}

/**
 * @class ValidationMixin
 * @extends Ember.Mixin
 */
export default Mixin.create({
  validationErrorMessages: null,
  lastIsInvalid: undefined,
  validationProperty: null, // property that validation should be based on

  init() {
    this._super(...arguments);
    assert('validationProperty must be set', this.get('validationProperty'));
    if (!this.get('validationErrorMessages')) {
      let computedValidationMessages = buildComputedValidationMessages(
        this.get('validationProperty'),
        this.validations(),
        this.get('customValidations')
      );
      this.set('validationErrorMessages', computedValidationMessages);
    }
  },

  /**
   * The result of isInvalid is appropriate for controlling the display of
   * validation error messages. It also may be used to distinguish whether
   * the input would be considered valid after it is touched.
   *
   * @public
   *
   * @return {boolean} Whether the input is or would be invalid.
   *    false: input is valid (touched or not), or is no longer rendered
   *    true: input has been touched and is invalid.
   */
  isInvalid: computed.or('validationErrorMessages.length'),
  isValid: computed.not('isInvalid'),

  /**
   * Return the built-in validations.
   *
   * May be overridden to provide additional built-in validations. Be sure to
   * call this._super() to retrieve the standard validations.
   *
   * @public
   */
  validations() {
    return [
      requiredValidator,
      minValidator,
      maxValidator,
      minlengthValidator,
      maxlengthValidator
    ];
  },

  notifyValidityChange() {
    let isValid = this.get('isValid');
    let lastIsValid = this.get('lastIsValid');
    if (lastIsValid !== isValid) {
      this.sendAction('onValidityChange', isValid);
      this.set('lastIsValid', isValid);
    }
  },
  customValidations: [],
  errors: []
});
<commit_msg>also trigger onValidityChange when isTouched changes<commit_after>/**
 * @module ember-paper
 */
import Ember from 'ember';

const { Mixin, computed, A, assert, isArray, Logger, get, String: { loc }, isBlank } = Ember;

import requiredValidator from 'ember-paper/validators/required';
import minValidator from 'ember-paper/validators/min';
import maxValidator from 'ember-paper/validators/max';
import minlengthValidator from 'ember-paper/validators/minlength';
import maxlengthValidator from 'ember-paper/validators/maxlength';

/**
 * In order to make validation generic it is required that components using the validation mixin
 * specify what property the validation logic should be based on.
 *
 * @public
 *
 * @return computed property that depends on the supplied property name
 */
function buildComputedValidationMessages(property, validations = [], customValidations = []) {
  let validationParams = validations.map((v) => get(v, 'param')).filter((v) => !isBlank(v));
  let customValidationParams = customValidations.map((v) => get(v, 'param')).filter((v) => !isBlank(v));

  return computed(property, 'errors.[]', 'customValidations.[]', ...validationParams, ...customValidationParams, function() {
    let validations = A();
    let messages = A();

    // built-in validations
    validations.pushObjects(this.validations());

    // custom validations
    let customValidations = this.get('customValidations');
    assert('`customValidations` must be an array', isArray(customValidations));
    validations.pushObjects(customValidations);

    // execute validations
    let currentValue = this.get(property);
    validations.forEach((validation) => {
      assert('validation must include an `validate(value)` function', validation && validation.validate && typeof validation.validate === 'function');
      try {
        let valParam = get(validation, 'param');
        let paramValue = valParam ? this.get(valParam) : undefined;
        if (!validation.validate(currentValue, paramValue)) {
          let message = this.get(`errorMessages.${valParam}`) || get(validation, 'message');
          messages.pushObject({
            message: loc(message.string || message, paramValue, currentValue)
          });
        }
      } catch(error) {
        Logger.error('Exception with validation: ', validation, error);
      }
    });

    // error messages array
    let errors = this.get('errors') || [];
    assert('`errors` must be an array', isArray(errors));
    messages.pushObjects(errors.map((e) => {
      return get(e, 'message') ? e : { message: e };
    }));

    return messages;
  });
}

/**
 * @class ValidationMixin
 * @extends Ember.Mixin
 */
export default Mixin.create({
  validationErrorMessages: null,
  lastIsInvalid: undefined,
  validationProperty: null, // property that validation should be based on

  init() {
    this._super(...arguments);
    assert('validationProperty must be set', this.get('validationProperty'));
    if (!this.get('validationErrorMessages')) {
      let computedValidationMessages = buildComputedValidationMessages(
        this.get('validationProperty'),
        this.validations(),
        this.get('customValidations')
      );
      this.set('validationErrorMessages', computedValidationMessages);
    }
  },

  /**
   * The result of isInvalid is appropriate for controlling the display of
   * validation error messages. It also may be used to distinguish whether
   * the input would be considered valid after it is touched.
   *
   * @public
   *
   * @return {boolean} Whether the input is or would be invalid.
   *    false: input is valid (touched or not), or is no longer rendered
   *    true: input has been touched and is invalid.
   */
  isInvalid: computed.or('validationErrorMessages.length'),
  isValid: computed.not('isInvalid'),

  /**
   * Return the built-in validations.
   *
   * May be overridden to provide additional built-in validations. Be sure to
   * call this._super() to retrieve the standard validations.
   *
   * @public
   */
  validations() {
    return [
      requiredValidator,
      minValidator,
      maxValidator,
      minlengthValidator,
      maxlengthValidator
    ];
  },

  notifyValidityChange() {
    let isValid = this.get('isValid');
    let lastIsValid = this.get('lastIsValid');
    let isTouched = this.get('isTouched');
    let lastIsTouched = this.get('lastIsTouched');
    if (lastIsValid !== isValid || lastIsTouched !== isTouched) {
      this.sendAction('onValidityChange', isValid);
      this.set('lastIsValid', isValid);
      this.set('lastIsTouched', isTouched);
    }
  },
  customValidations: [],
  errors: []
});
<|endoftext|>


<commit_before>//{namespace name=backend/connect/view/main}

//{block name="backend/connect/view/export/product/list"}
Ext.define('Shopware.apps.Connect.view.export.product.List', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.connect-export-list',

    border: false,

    store: 'export.List',

    selModel: {
        selType: 'checkboxmodel',
        mode: 'MULTI'
    },

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            dockedItems: [
                me.getPagingToolbar()
            ],
            columns: me.getColumns()
        });

        me.callParent(arguments);
    },

    getColumns: function() {
        return [{
            header: '{s name=export/columns/number}Number{/s}',
            dataIndex: 'number',
            flex: 2
        }, {
            header: '{s name=export/columns/name}Name{/s}',
            dataIndex: 'name',
            flex: 4
        }, {
            header: '{s name=export/columns/supplier}Supplier{/s}',
            dataIndex: 'supplier',
            flex: 3
        }, {
            header: '{s name=export/columns/active}Active{/s}',
            xtype: 'booleancolumn',
            dataIndex: 'active',
            width: 50,
            sortable: false
        }, {
            header: '{s name=export/columns/price}Price{/s}',
            xtype: 'numbercolumn',
            dataIndex: 'price',
            align: 'right',
            width: 55
        }, {
            header: '{s name=export/columns/tax}Tax{/s}',
            xtype: 'numbercolumn',
            dataIndex: 'tax',
            align: 'right',
            flex: 1
        }, {
            header: '{s name=export/columns/stock}Stock{/s}',
            xtype: 'numbercolumn',
            dataIndex: 'inStock',
            format: '0,000',
            align: 'right',
            flex: 1
        },
            {
            header: '{s name=export/columns/status}Status{/s}',
            dataIndex: 'exportStatus',
            flex: 1,
            renderer: function(value, metaData, record) {
                var className;
                if (value == 'insert') {
                    className = 'sprite-tick-circle';
                } else if (value == 'update') {
                    className = 'sprite-arrow-circle-135';
                } else if (value == 'error') {
                    className = 'sprite-minus-circle-frame';
                }

                if(record.get('exportMessage')) {
                    metaData.tdAttr = 'data-qtip="' +  record.get('exportMessage') + '"';
                } else {
                    metaData.tdAttr = 'data-qtip="' +  value + '"';
                }

                return '

';
            }
        }, {
            xtype: 'actioncolumn',
            width: 26,
            items: [{
                action: 'edit',
                cls: 'editBtn',
                iconCls: 'sprite-pencil',
                handler: function(view, rowIndex, colIndex, item, opts, record) {
                    Shopware.app.Application.addSubApplication({
                        name: 'Shopware.apps.Article',
                        action: 'detail',
                        params: {
                            articleId: record.get('id')
                        }
                    });
                }
            }]
        }];
    },

    /**
     * Creates a paging toolbar with additional page size selector
     *
     * @returns Array
     */
    getPagingToolbar: function() {
        var me = this;
        var pageSize = Ext.create('Ext.form.field.ComboBox', {
            labelWidth: 120,
            cls: Ext.baseCSSPrefix + 'page-size',
            queryMode: 'local',
            width: 180,
            listeners: {
                scope: me,
                select: function(combo, records) {
                    var record = records[0],
                        me = this;

                    me.store.pageSize = record.get('value');
                    me.store.loadPage(1);
                }
            },
            store: Ext.create('Ext.data.Store', {
                fields: [ 'value' ],
                data: [
                    { value: '20' },
                    { value: '40' },
                    { value: '60' },
                    { value: '80' },
                    { value: '100' },
                    { value: '250' }
                ]
            }),
            displayField: 'value',
            valueField: 'value',
            editable: false,
            emptyText: '20'
        });
        pageSize.setValue(me.store.pageSize);

        var pagingBar = Ext.create('Ext.toolbar.Paging', {
            store: me.store,
            dock:'bottom',
            displayInfo:true
        });

        pagingBar.insert(pagingBar.items.length - 2, [ { xtype: 'tbspacer', width: 6 }, pageSize ]);
        return pagingBar;
    }
});
//{/block}<commit_msg>[CON-3138] Fixed code styles<commit_after>//{namespace name=backend/connect/view/main}

//{block name="backend/connect/view/export/product/list"}
Ext.define('Shopware.apps.Connect.view.export.product.List', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.connect-export-list',

    border: false,

    store: 'export.List',

    selModel: {
        selType: 'checkboxmodel',
        mode: 'MULTI'
    },

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            dockedItems: [
                me.getPagingToolbar()
            ],
            columns: me.getColumns()
        });

        me.callParent(arguments);
    },

    getColumns: function() {
        return [{
            header: '{s name=export/columns/number}Number{/s}',
            dataIndex: 'number',
            flex: 2
        }, {
            header: '{s name=export/columns/name}Name{/s}',
            dataIndex: 'name',
            flex: 4
        }, {
            header: '{s name=export/columns/supplier}Supplier{/s}',
            dataIndex: 'supplier',
            flex: 3
        }, {
            header: '{s name=export/columns/active}Active{/s}',
            xtype: 'booleancolumn',
            dataIndex: 'active',
            width: 50,
            sortable: false
        }, {
            header: '{s name=export/columns/price}Price{/s}',
            xtype: 'numbercolumn',
            dataIndex: 'price',
            align: 'right',
            width: 55
        }, {
            header: '{s name=export/columns/tax}Tax{/s}',
            xtype: 'numbercolumn',
            dataIndex: 'tax',
            align: 'right',
            flex: 1
        }, {
            header: '{s name=export/columns/stock}Stock{/s}',
            xtype: 'numbercolumn',
            dataIndex: 'inStock',
            format: '0,000',
            align: 'right',
            flex: 1
        }, {
            header: '{s name=export/columns/status}Status{/s}',
            dataIndex: 'exportStatus',
            flex: 1,
            renderer: function(value, metaData, record) {
                var className;
                if (value == 'insert') {
                    className = 'sprite-tick-circle';
                } else if (value == 'update') {
                    className = 'sprite-arrow-circle-135';
                } else if (value == 'error') {
                    className = 'sprite-minus-circle-frame';
                }

                if(record.get('exportMessage')) {
                    metaData.tdAttr = 'data-qtip="' +  record.get('exportMessage') + '"';
                } else {
                    metaData.tdAttr = 'data-qtip="' +  value + '"';
                }

                return '

';
            }
        }, {
            xtype: 'actioncolumn',
            width: 26,
            items: [{
                action: 'edit',
                cls: 'editBtn',
                iconCls: 'sprite-pencil',
                handler: function(view, rowIndex, colIndex, item, opts, record) {
                    Shopware.app.Application.addSubApplication({
                        name: 'Shopware.apps.Article',
                        action: 'detail',
                        params: {
                            articleId: record.get('id')
                        }
                    });
                }
            }]
        }];
    },

    /**
     * Creates a paging toolbar with additional page size selector
     *
     * @returns Array
     */
    getPagingToolbar: function() {
        var me = this;
        var pageSize = Ext.create('Ext.form.field.ComboBox', {
            labelWidth: 120,
            cls: Ext.baseCSSPrefix + 'page-size',
            queryMode: 'local',
            width: 180,
            listeners: {
                scope: me,
                select: function(combo, records) {
                    var record = records[0],
                        me = this;

                    me.store.pageSize = record.get('value');
                    me.store.loadPage(1);
                }
            },
            store: Ext.create('Ext.data.Store', {
                fields: [ 'value' ],
                data: [
                    { value: '20' },
                    { value: '40' },
                    { value: '60' },
                    { value: '80' },
                    { value: '100' },
                    { value: '250' }
                ]
            }),
            displayField: 'value',
            valueField: 'value',
            editable: false,
            emptyText: '20'
        });
        pageSize.setValue(me.store.pageSize);

        var pagingBar = Ext.create('Ext.toolbar.Paging', {
            store: me.store,
            dock:'bottom',
            displayInfo:true
        });

        pagingBar.insert(pagingBar.items.length - 2, [ { xtype: 'tbspacer', width: 6 }, pageSize ]);
        return pagingBar;
    }
});
//{/block}<|endoftext|>


<commit_before>window.isSmartphone = function() {
  // this check is also used in main.js. Note it should not detect
  // tablets because their display is large enough to use the desktop
  // version.

  // The stock intel site allows forcing mobile/full sites with a vp=m or vp=f
  // parameter - let's support the same. (stock only allows this for some
  // browsers - e.g. android phone/tablet. let's allow it for all, but
  // no promises it'll work right)
  var viewParam = getURLParam('vp');
  if (viewParam == 'm') return true;
  if (viewParam == 'f') return false;

  return navigator.userAgent.match(/Android.*Mobile/);
}

window.smartphone = function() {};

window.runOnSmartphonesBeforeBoot = function() {
  if(!isSmartphone()) return;
  console.warn('running smartphone pre boot stuff');

  // add smartphone stylesheet
  headHTML = document.getElementsByTagName('head')[0].innerHTML;
  headHTML += '';
  document.getElementsByTagName('head')[0].innerHTML = headHTML;

  // don’t need many of those
  window.setupStyles = function() {
    $('head').append('');
  }

  window.smartphone.mapButton = $('map').click(function() {
    $('#chat, #chatinput, #scrollwrapper').hide();
    $('#map').css('visibility', 'visible');
    $('#updatestatus').show();
    $('#chatcontrols a .active').removeClass('active');
    $("#chatcontrols a:contains('map')").addClass('active');
  });

  window.smartphone.sideButton = $('info').click(function() {
    $('#chat, #chatinput, #updatestatus').hide();
    $('#map').css('visibility', 'hidden');
    $('#scrollwrapper').show();
    $('.active').removeClass('active');
    $("#chatcontrols a:contains('info')").addClass('active');
  });

  $('#chatcontrols').append(smartphone.mapButton).append(smartphone.sideButton);

  window.addHook('portalDetailsUpdated', function(data) {
    var x = $('.imgpreview img').removeClass('hide');

    if(!x.length) {
      $('.fullimg').remove();
      return;
    }

    if($('.fullimg').length) {
      $('.fullimg').replaceWith(x.addClass('fullimg'));
    } else {
      x.addClass('fullimg').appendTo('#sidebar');
    }
  });
}

window.runOnSmartphonesAfterBoot = function() {
  if(!isSmartphone()) return;
  console.warn('running smartphone post boot stuff');

  smartphone.mapButton.click();

  // disable img full view
  $('#portaldetails').off('click', '**');

  // make buttons in action bar flexible
  var l = $('#chatcontrols a:visible');
  l.css('width', 100/l.length + '%');

  // add event to portals that allows long press to switch to sidebar
  window.addHook('portalAdded', function(data) {
    data.portal.on('add', function() {
      if(!this._container || this.options.addedTapHoldHandler) return;
      this.options.addedTapHoldHandler = true;
      var guid = this.options.guid;

      // this is a hack, accessing Leaflet’s private _container is evil
      $(this._container).on('taphold', function() {
        window.renderPortalDetails(guid);
        window.smartphone.sideButton.click();
      });
    });
  });

  // Force lower render limits for mobile
  window.VIEWPORT_PAD_RATIO = 0.1;
  window.MAX_DRAWN_PORTALS = 500;
  window.MAX_DRAWN_LINKS = 200;
  window.MAX_DRAWN_FIELDS = 100;

  //hook some additional code into the LayerControl so it's easy for the mobile app to interface with it
  //WARNING: does depend on internals of the L.Control.Layers code
  window.layerChooser.getLayers = function() {
    var baseLayers = new Array();
    var overlayLayers = new Array();

    for (i in this._layers) {
      var obj = this._layers[i];
      var layerActive = window.map.hasLayer(obj.layer);
      var info = {
        layerId: L.stamp(obj.layer),
        name: obj.name,
        active: layerActive
      }
      if (obj.overlay) {
        overlayLayers.push(info);
      } else {
        baseLayers.push(info);
      }
    }

    var overlayLayersJSON = JSON.stringify(overlayLayers);
    var baseLayersJSON = JSON.stringify(baseLayers);

    if (typeof android !== 'undefined' && android && android.setLayers) {
        android.setLayers(baseLayersJSON, overlayLayersJSON);
    }

    return {
      baseLayers: baseLayers,
      overlayLayers: overlayLayers
    }
  }
  window.layerChooser.showLayer = function(id,show) {
    window.console.log('yeay' + id + show);
    if (show === undefined) show = true;
    obj = this._layers[id];
    if (!obj) return false;

    if(show) {
      if (!this._map.hasLayer(obj.layer)) {
        //the layer to show is not currently active
        this._map.addLayer(obj.layer);

        //if it's an overlay, remove any others
        if (!obj.overlay) {
          for(i in this._layers) {
            if (i != id) {
              var other = this._layers[i];
              if (!other.overlay && this._map.hasLayer(other.layer)) this._map.removeLayer(other.layer);
            }
          }
        }
      }
    } else {
      if (this._map.hasLayer(obj.layer)) {
        this._map.removeLayer(obj.layer);
      }
    }
    //below logic based on code in L.Control.Layers _onInputClick
    if(!obj.overlay) {
      this._map.setZoom(this._map.getZoom());
      this._map.fire('baselayerchange', {layer: obj.layer});
    }

    return true;
  }

}
<commit_msg>remove debug console.log, fix comment<commit_after>window.isSmartphone = function() {
  // this check is also used in main.js. Note it should not detect
  // tablets because their display is large enough to use the desktop
  // version.

  // The stock intel site allows forcing mobile/full sites with a vp=m or vp=f
  // parameter - let's support the same. (stock only allows this for some
  // browsers - e.g. android phone/tablet. let's allow it for all, but
  // no promises it'll work right)
  var viewParam = getURLParam('vp');
  if (viewParam == 'm') return true;
  if (viewParam == 'f') return false;

  return navigator.userAgent.match(/Android.*Mobile/);
}

window.smartphone = function() {};

window.runOnSmartphonesBeforeBoot = function() {
  if(!isSmartphone()) return;
  console.warn('running smartphone pre boot stuff');

  // add smartphone stylesheet
  headHTML = document.getElementsByTagName('head')[0].innerHTML;
  headHTML += '';
  document.getElementsByTagName('head')[0].innerHTML = headHTML;

  // don’t need many of those
  window.setupStyles = function() {
    $('head').append('');
  }

  window.smartphone.mapButton = $('map').click(function() {
    $('#chat, #chatinput, #scrollwrapper').hide();
    $('#map').css('visibility', 'visible');
    $('#updatestatus').show();
    $('#chatcontrols a .active').removeClass('active');
    $("#chatcontrols a:contains('map')").addClass('active');
  });

  window.smartphone.sideButton = $('info').click(function() {
    $('#chat, #chatinput, #updatestatus').hide();
    $('#map').css('visibility', 'hidden');
    $('#scrollwrapper').show();
    $('.active').removeClass('active');
    $("#chatcontrols a:contains('info')").addClass('active');
  });

  $('#chatcontrols').append(smartphone.mapButton).append(smartphone.sideButton);

  window.addHook('portalDetailsUpdated', function(data) {
    var x = $('.imgpreview img').removeClass('hide');

    if(!x.length) {
      $('.fullimg').remove();
      return;
    }

    if($('.fullimg').length) {
      $('.fullimg').replaceWith(x.addClass('fullimg'));
    } else {
      x.addClass('fullimg').appendTo('#sidebar');
    }
  });
}

window.runOnSmartphonesAfterBoot = function() {
  if(!isSmartphone()) return;
  console.warn('running smartphone post boot stuff');

  smartphone.mapButton.click();

  // disable img full view
  $('#portaldetails').off('click', '**');

  // make buttons in action bar flexible
  var l = $('#chatcontrols a:visible');
  l.css('width', 100/l.length + '%');

  // add event to portals that allows long press to switch to sidebar
  window.addHook('portalAdded', function(data) {
    data.portal.on('add', function() {
      if(!this._container || this.options.addedTapHoldHandler) return;
      this.options.addedTapHoldHandler = true;
      var guid = this.options.guid;

      // this is a hack, accessing Leaflet’s private _container is evil
      $(this._container).on('taphold', function() {
        window.renderPortalDetails(guid);
        window.smartphone.sideButton.click();
      });
    });
  });

  // Force lower render limits for mobile
  window.VIEWPORT_PAD_RATIO = 0.1;
  window.MAX_DRAWN_PORTALS = 500;
  window.MAX_DRAWN_LINKS = 200;
  window.MAX_DRAWN_FIELDS = 100;

  //hook some additional code into the LayerControl so it's easy for the mobile app to interface with it
  //WARNING: does depend on internals of the L.Control.Layers code
  window.layerChooser.getLayers = function() {
    var baseLayers = new Array();
    var overlayLayers = new Array();

    for (i in this._layers) {
      var obj = this._layers[i];
      var layerActive = window.map.hasLayer(obj.layer);
      var info = {
        layerId: L.stamp(obj.layer),
        name: obj.name,
        active: layerActive
      }
      if (obj.overlay) {
        overlayLayers.push(info);
      } else {
        baseLayers.push(info);
      }
    }

    var overlayLayersJSON = JSON.stringify(overlayLayers);
    var baseLayersJSON = JSON.stringify(baseLayers);

    if (typeof android !== 'undefined' && android && android.setLayers) {
        android.setLayers(baseLayersJSON, overlayLayersJSON);
    }

    return {
      baseLayers: baseLayers,
      overlayLayers: overlayLayers
    }
  }
  window.layerChooser.showLayer = function(id,show) {
    if (show === undefined) show = true;
    obj = this._layers[id];
    if (!obj) return false;

    if(show) {
      if (!this._map.hasLayer(obj.layer)) {
        //the layer to show is not currently active
        this._map.addLayer(obj.layer);

        //if it's a base layer, remove any others
        if (!obj.overlay) {
          for(i in this._layers) {
            if (i != id) {
              var other = this._layers[i];
              if (!other.overlay && this._map.hasLayer(other.layer)) this._map.removeLayer(other.layer);
            }
          }
        }
      }
    } else {
      if (this._map.hasLayer(obj.layer)) {
        this._map.removeLayer(obj.layer);
      }
    }

    //below logic based on code in L.Control.Layers _onInputClick
    if(!obj.overlay) {
      this._map.setZoom(this._map.getZoom());
      this._map.fire('baselayerchange', {layer: obj.layer});
    }

    return true;
  }

}
<|endoftext|>


<commit_before>var util = require('util');
var bcrypt = require('bcrypt');
var ProtoStore = require('passwordless-tokenstore');
var mysql = require("mysql");

/**
 * Constructor of Store
 * @param {String} conString URI as defined by the PostgreSQL specification. Please
 * check the documentation for details:
 * https://github.com/brianc/node-postgres
 * @param {Object} [options] Combines both the options for the PostgreClient as well
 * as the options for Store. For the PostgreClient options please refer back to
 * the documentation. Store understands the following options:
 * @constructor
 */
function Store(conString, options) {
  var self = this;
  this._table = "passwordless";
  this._client = mysql.createPool(conString);
  this._client.query("CREATE TABLE IF NOT EXISTS " + this._table + " " +
    "( id serial NOT NULL, uid character varying(160), token character varying(60) NOT NULL, origin text NOT NULL, ttl bigint, " +
    "CONSTRAINT passwordless_pkey PRIMARY KEY (id), CONSTRAINT passwordless_token_key UNIQUE (token), CONSTRAINT passwordless_uid_key UNIQUE (uid) )");
}
util.inherits(Store, ProtoStore);

/**
 * Checks if the provided token / user id combination exists and is
 * valid in terms of time-to-live. If yes, the method provides the
 * the stored referrer URL if any.
 * @param  {String}   token to be authenticated
 * @param  {String}   uid Unique identifier of an user
 * @param  {Function} callback in the format (error, valid, referrer).
 * In case of error, error will provide details, valid will be false and
 * referrer will be null. If the token / uid combination was not found
 * found, valid will be false and all else null. Otherwise, valid will
 * be true, referrer will (if provided when the token was stored) the
 * original URL requested and error will be null.
 */
Store.prototype.authenticate = function(token, uid, callback) {
  if(!token || !uid || !callback) {
    throw new Error('TokenStore:authenticate called with invalid parameters');
  }

  var self = this;

  self._client.query('SELECT * FROM ' + self._table + ' WHERE uid=?',[uid], function(err, result) {
    if(err) {
      return callback(err, false, null);
    }
    if(!result || !result || !result.length || (result && result.length > 1)) {
      return callback(null, false, null);
    } else if(Date.now() > result[0].ttl) {
      callback(null, false, null);
    } else {
      bcrypt.compare(token, result[0].token, function(err, res) {
        if(err) {
          return callback(err, false, null);
        }

        if(res) {
          callback(null, true, result[0].origin);
        } else {
          callback(null, false, null);
        }
      });
    }
  });
};

/**
 * Stores a new token / user ID combination or updates the token of an
 * existing user ID if that ID already exists. Hence, a user can only
 * have one valid token at a time
 * @param  {String}   token Token that allows authentication of _uid_
 * @param  {String}   uid Unique identifier of an user
 * @param  {Number}   msToLive Validity of the token in ms
 * @param  {String}   originUrl Originally requested URL or null
 * @param  {Function} callback Called with callback(error) in case of an
 * error or as callback() if the token was successully stored / updated
 */
Store.prototype.storeOrUpdate = function(token, uid, msToLive, originUrl, callback) {
  if(!token || !uid || !msToLive || !callback || isNaN(msToLive)) {
    throw new Error('TokenStore:storeOrUpdate called with invalid parameters');
  }

  var self = this;
  bcrypt.hash(token, 10, function(err, hashedToken) {
    if(err) {
      return callback(err);
    }
    self._client.query('INSERT INTO ' + self._table + '(uid, token, origin, ttl) VALUES(?, ?, ?, ?)',[uid, hashedToken, originUrl, (Date.now() + msToLive)], function(err) {
      if(err){
        self._client.query('UPDATE ' + self._table + ' SET token=?, origin=?, ttl=? WHERE uid=?',[hashedToken, originUrl, (Date.now() + msToLive), uid], function(err) {
          if(err){
            callback(err);
          }else{
            callback();
          }
        });
      }else{
        callback();
      }
    });
  });
};

/**
 * Invalidates and removes a user and the linked token
 * @param  {String} uid  user ID
 * @param  {Function} callback called with callback(error) in case of an
 * error or as callback() if the uid was successully invalidated
 */
Store.prototype.invalidateUser = function(uid, callback) {
  if(!uid || !callback) {
    throw new Error('TokenStore:invalidateUser called with invalid parameters');
  }

  this._client.query('DELETE FROM ' + this._table + ' WHERE uid=?',[uid], function(err) {
    if(err){
      return callback(err);
    }

    callback();
  });
};

/**
 * Removes and invalidates all token
 * @param  {Function} callback Called with callback(error) in case of an
 * error or as callback() otherwise
 */
Store.prototype.clear = function(callback) {
  if(!callback) {
    throw new Error('TokenStore:clear called with invalid parameters');
  }

  this._client.query('DELETE FROM ' + this._table, function(err) {
    if(err){
      return callback(err);
    }

    callback();
  });
};

/**
 * Number of tokens stored (no matter the validity)
 * @param  {Function} callback Called with callback(null, count) in case
 * of success or with callback(error) in case of an error
 */
Store.prototype.length = function(callback) {
  if(!callback) {
    throw new Error('TokenStore:length called with invalid parameters');
  }

  this._client.query('SELECT COUNT(uid) FROM ' + this._table, function(err, result) {
    if(err){
      return callback(err);
    }

    callback(null, parseInt(result[0]['COUNT(uid)']));
  });
};

Store.prototype.disconnect = function(callback) {
  this._client.end(callback);
};

module.exports = Store;<commit_msg>Updated the docs<commit_after>var util = require('util');
var bcrypt = require('bcrypt');
var ProtoStore = require('passwordless-tokenstore');
var mysql = require("mysql");

/**
 * Constructor of Store
 * @param {String} conString URI as defined by the MySQL specification.
 * @param {Object} [options] Combines both the options for the MySQL Client as well
 * as the options for Store. For the MySQL Client options please refer back to
 * the documentation.
 * @constructor
 */
function Store(conString, options) {
  var self = this;
  this._table = "passwordless";
  this._client = mysql.createPool(conString);
  this._client.query("CREATE TABLE IF NOT EXISTS " + this._table + " " +
    "( id serial NOT NULL, uid character varying(160), token character varying(60) NOT NULL, origin text NOT NULL, ttl bigint, " +
    "CONSTRAINT passwordless_pkey PRIMARY KEY (id), CONSTRAINT passwordless_token_key UNIQUE (token), CONSTRAINT passwordless_uid_key UNIQUE (uid) )");
}

util.inherits(Store, ProtoStore);

/**
 * Checks if the provided token / user id combination exists and is
 * valid in terms of time-to-live. If yes, the method provides the
 * the stored referrer URL if any.
 * @param  {String}   token to be authenticated
 * @param  {String}   uid Unique identifier of an user
 * @param  {Function} callback in the format (error, valid, referrer).
 * In case of error, error will provide details, valid will be false and
 * referrer will be null. If the token / uid combination was not found
 * found, valid will be false and all else null. Otherwise, valid will
 * be true, referrer will (if provided when the token was stored) the
 * original URL requested and error will be null.
 */
Store.prototype.authenticate = function(token, uid, callback) {
  if(!token || !uid || !callback) {
    throw new Error('TokenStore:authenticate called with invalid parameters');
  }

  var self = this;

  self._client.query('SELECT * FROM ' + self._table + ' WHERE uid=?',[uid], function(err, result) {
    if(err) {
      return callback(err, false, null);
    }
    if(!result || !result || !result.length || (result && result.length > 1)) {
      return callback(null, false, null);
    } else if(Date.now() > result[0].ttl) {
      callback(null, false, null);
    } else {
      bcrypt.compare(token, result[0].token, function(err, res) {
        if(err) {
          return callback(err, false, null);
        }

        if(res) {
          callback(null, true, result[0].origin);
        } else {
          callback(null, false, null);
        }
      });
    }
  });
};

/**
 * Stores a new token / user ID combination or updates the token of an
 * existing user ID if that ID already exists. Hence, a user can only
 * have one valid token at a time
 * @param  {String}   token Token that allows authentication of _uid_
 * @param  {String}   uid Unique identifier of an user
 * @param  {Number}   msToLive Validity of the token in ms
 * @param  {String}   originUrl Originally requested URL or null
 * @param  {Function} callback Called with callback(error) in case of an
 * error or as callback() if the token was successully stored / updated
 */
Store.prototype.storeOrUpdate = function(token, uid, msToLive, originUrl, callback) {
  if(!token || !uid || !msToLive || !callback || isNaN(msToLive)) {
    throw new Error('TokenStore:storeOrUpdate called with invalid parameters');
  }

  var self = this;
  bcrypt.hash(token, 10, function(err, hashedToken) {
    if(err) {
      return callback(err);
    }
    self._client.query('INSERT INTO ' + self._table + '(uid, token, origin, ttl) VALUES(?, ?, ?, ?)',[uid, hashedToken, originUrl, (Date.now() + msToLive)], function(err) {
      if(err){
        self._client.query('UPDATE ' + self._table + ' SET token=?, origin=?, ttl=? WHERE uid=?',[hashedToken, originUrl, (Date.now() + msToLive), uid], function(err) {
          if(err){
            callback(err);
          }else{
            callback();
          }
        });
      }else{
        callback();
      }
    });
  });
};

/**
 * Invalidates and removes a user and the linked token
 * @param  {String} uid  user ID
 * @param  {Function} callback called with callback(error) in case of an
 * error or as callback() if the uid was successully invalidated
 */
Store.prototype.invalidateUser = function(uid, callback) {
  if(!uid || !callback) {
    throw new Error('TokenStore:invalidateUser called with invalid parameters');
  }

  this._client.query('DELETE FROM ' + this._table + ' WHERE uid=?',[uid], function(err) {
    if(err){
      return callback(err);
    }

    callback();
  });
};

/**
 * Removes and invalidates all token
 * @param  {Function} callback Called with callback(error) in case of an
 * error or as callback() otherwise
 */
Store.prototype.clear = function(callback) {
  if(!callback) {
    throw new Error('TokenStore:clear called with invalid parameters');
  }

  this._client.query('DELETE FROM ' + this._table, function(err) {
    if(err){
      return callback(err);
    }

    callback();
  });
};

/**
 * Number of tokens stored (no matter the validity)
 * @param  {Function} callback Called with callback(null, count) in case
 * of success or with callback(error) in case of an error
 */
Store.prototype.length = function(callback) {
  if(!callback) {
    throw new Error('TokenStore:length called with invalid parameters');
  }

  this._client.query('SELECT COUNT(uid) FROM ' + this._table, function(err, result) {
    if(err){
      return callback(err);
    }

    callback(null, parseInt(result[0]['COUNT(uid)']));
  });
};

Store.prototype.disconnect = function(callback) {
  this._client.end(callback);
};

module.exports = Store;<|endoftext|>


<commit_before>var restify = require('restify');
var mongojs = require('mongojs');

var db = mongojs('localhost:27017', ['netdata']);

var server = restify.createServer({
		name: 'backpacklistener',
});

server.listen(3001);

server.post('/netdata', function create(req, res, next) {

		var body = '';
    req.on('data', function (data) {
        body += data;
				// console.log(body.toString());
    });
    req.on('end', function () {
				// simple search for bad domain connect.facebook.net
				// nslookup: 23.73.127.228
				var stringbody = body.toString();
				var facedetect = stringbody.indexOf("facebook");
				if (facedetect != -1) { // we found facebook
						// find where it came from
						var regpattern = /www\.(.*)\.com/;
						var result = stringbody.match(regpattern);
						// console.log(result)
						result[0]
				}

				// TODO DB storage and non-crazy searching
				// db.netdata.save(product,
  			// 								function (err, data) {
  			// 										res.writeHead(200, {
  			// 												'Content-Type': 'application/json; charset=utf-8'
  			// 										});
  			// 										res.end(JSON.stringify(data));
  			// 								});
    });
		res.end('AAAAAAAAAAAAA');
});
<commit_msg>blind mongo insert shitparty<commit_after>var restify = require('restify');
var mongojs = require('mongojs');

var db = mongojs('localhost:27017', ['backpack']);
var alerts = db.collection('alerts');

var server = restify.createServer({
		name: 'backpacklistener',
});

server.listen(3001);

server.post('/netdata', function create(req, res, next) {

		var body = '';
    req.on('data', function (data) {
        body += data;
    });
    req.on('end', function () {
				// simple search for bad domain connect.facebook.net
				// nslookup: 23.73.127.228
				var stringbody = body.toString();
				var facedetect = stringbody.indexOf("facebook");
				if (facedetect != -1) { // we found facebook
						// find where it came from
						var regpattern = /www\.(.*)\.com/;
						var result = stringbody.match(regpattern);
						// store alert's result domain
						alerts.insert(result[0],
													function (err, data) {

													});

				}

				// TODO DB storage and non-crazy searching
				// db.netdata.save(product,
  			// 								function (err, data) {
  			// 										res.writeHead(200, {
  			// 												'Content-Type': 'application/json; charset=utf-8'
  			// 										});
  			// 										res.end(JSON.stringify(data));
  			// 								});
    });
		res.end('AAAAAAAAAAAAA');
});
<|endoftext|>