<commit_before>Teikei.module("Places", function(Places, Teikei, Backbone, Marionette, $, _) {

  var IMAGE_PLACEHOLDER = '/assets/placeimage-placeholder.png';

  Places.DetailsView = Teikei.Base.ItemView.extend({

    className: "details-view",
    template: "places/details",
    templateHelpers: _.extend({
      timeago: $.timeago,
      ownedByCurrentUser: function() {
        var result = false;
        if (this.ownerships.length > 0 && Teikei.currentUser) {
          var currentUserOwnerships = this.ownerships.filter(function(o) {
            return o.user_id === Teikei.currentUser.get('id');
          });
          result = currentUserOwnerships.length > 0;
        }
        return result;

      },
      placesFilteredByType: function(places, type) {
        return _.filter(places, function(place) {
          return place.type === type;
        });
      },
      temporalConnectionWord: function(year, month) {
        var foundedAt = new Date(year, month);
        var today = new Date();
        var inThePast = foundedAt < today;
        return (inThePast) ? I18n.t('forms.labels.since') : I18n.t('forms.labels.from');
      },
      getContactName: function() {
        var name = "";
        if (this.ownerships.length > 0) {
          name = I18n.t("forms.labels.name") + ": " + this.ownerships[0].name;
        }
        return name;
      },
      getContactPhone: function() {
        var phone = "";
        if (this.ownerships.length > 0) {
          var firstOwnerPhone = this.ownerships[0].phone;
          if (firstOwnerPhone !== null && firstOwnerPhone !== "" ) {
            phone = I18n.t("forms.labels.phone") + ": " + firstOwnerPhone;
          }
        }
        return phone;
      },
      getImageUrl: function() {
        var imageUrl = IMAGE_PLACEHOLDER;
        if (this.image) {
          imageUrl = this.image.url;
        }
        return imageUrl;
      },
      translatedProducts: function(farm) {
        return _.union(farm.animal_products,
          farm.vegetable_products,
          farm.beverages).map(function(p) {
            return I18n.t('products.' + p);
          }).join(', ');
      }
    }),

    ui: {
      infoTab: "#info-tab",
      contactTab: "#contact-tab",
      membershipTab: "#membership-tab",
      infoPane: "#info",
      contactPane: "#contact",
      membershipPane: "#membership",
      placeMessageFormContainer: "#place-message-form-container",
      submitButton: ".submit"
    },

    events: {
      "click #info-tab": "onInfoTabClick",
      "click #membership-tab": "onMembershipTabClick",
      "click #contact-tab": "onContactTabClick",
      "click .call-to-action": "onMembershipPromoClick",
      "click .submit": "onSubmitClick",
      "click #edit-place": "onEditPlace"
    },

    // Override this with a schema for the actual form:
    schemata: {},

    initialize: function() {
      Teikei.vent.on("place:message:success", this.showSuccessMessage, this);
      Teikei.vent.on("place:message:failure", this.showFailureMessage, this);
    },

    onRender: function() {
      var $container = this.ui.placeMessageFormContainer;
      var ownercount = this.model.get("ownerships").length;
      var schemata = this.schemata();
      var forms = [];

      _.each(schemata, function(schema, formId) {
        var templateFile;

        if (formId !== "placeMessageForm" || (formId === "placeMessageForm" && ownercount > 0)) {
          templateFile = Marionette.Renderer.render("places/details/" + formId);
          var form = new Backbone.Form({
            model: this.model,
            schema: schema,
            template: _.template(templateFile)
          }).render();

          forms.push(form);
          form.$el.hide();
          $container.append(form.$el);
        } else {
          templateFile = Marionette.Renderer.render("places/details/placeMessageNoOwner");
          $container.append(_.template(templateFile));
        }

      }, this);

      _.defer(function() {
        forms[0].$el.show();
      });

      this.forms = forms;
      this.step = 0;
      this.bindUIElements();
    },

    onEditPlace: function(event) {
      event.preventDefault();
      Teikei.vent.trigger("edit:entry", this.model);
    },

    onSubmitClick: function(event) {
      event.preventDefault();

      var model = this.model;
      var forms = this.forms;
      var errors = forms[this.step].validate();
      var data = forms[this.step].getValue();

      if (errors === null) {
        this.hideAlertMessage(true);
        this.trigger("placeMessageForm:submit", {
          place_id: model.id,
          name: data.placeMessageName,
          email: data.placeMessageEmail,
          message: data.placeMessageMessage
        });
      }
    },

    showSuccessMessage: function(message) {
      this.showAlertMessage(message, "success");
      var form = this.forms[this.step];
      this.clearForm(form);
    },

    clearForm: function(form) {
      form.setValue("placeMessageName", "");
      form.setValue("placeMessageEmail", "");
      form.setValue("placeMessageMessage", "");
    },

    showFailureMessage: function(xhr) {
      this.showError(xhr, I18n.t("forms.messages.sending_email_failed"));
    },

    onInfoTabClick: function(event) {
      event.preventDefault();
      this.ui.infoTab.addClass("active");
      this.ui.membershipTab.removeClass("active");
      this.ui.contactTab.removeClass("active");
      this.ui.infoPane.addClass("active");
      this.ui.membershipPane.removeClass("active");
      this.ui.contactPane.removeClass("active");
    },

    onContactTabClick: function(event) {
      event.preventDefault();
      this.ui.infoTab.removeClass("active");
      this.ui.membershipTab.removeClass("active");
      this.ui.contactTab.addClass("active");
      this.ui.infoPane.removeClass("active");
      this.ui.membershipPane.removeClass("active");
      this.ui.contactPane.addClass("active");
    },

    onMembershipTabClick: function(event) {
      event.preventDefault();
      this.ui.infoTab.removeClass("active");
      this.ui.membershipTab.addClass("active");
      this.ui.contactTab.removeClass("active");
      this.ui.infoPane.removeClass("active");
      this.ui.membershipPane.addClass("active");
      this.ui.contactPane.removeClass("active");
    },

    onMembershipPromoClick: function(event) {
      this.ui.membershipTab.click();
    }
  });
});
<commit_msg>Include cases where firstOwnerPhone is undefined.<commit_after>Teikei.module("Places", function(Places, Teikei, Backbone, Marionette, $, _) {

  var IMAGE_PLACEHOLDER = '/assets/placeimage-placeholder.png';

  Places.DetailsView = Teikei.Base.ItemView.extend({

    className: "details-view",
    template: "places/details",
    templateHelpers: _.extend({
      timeago: $.timeago,
      ownedByCurrentUser: function() {
        var result = false;
        if (this.ownerships.length > 0 && Teikei.currentUser) {
          var currentUserOwnerships = this.ownerships.filter(function(o) {
            return o.user_id === Teikei.currentUser.get('id');
          });
          result = currentUserOwnerships.length > 0;
        }
        return result;

      },
      placesFilteredByType: function(places, type) {
        return _.filter(places, function(place) {
          return place.type === type;
        });
      },
      temporalConnectionWord: function(year, month) {
        var foundedAt = new Date(year, month);
        var today = new Date();
        var inThePast = foundedAt < today;
        return (inThePast) ? I18n.t('forms.labels.since') : I18n.t('forms.labels.from');
      },
      getContactName: function() {
        var name = "";
        if (this.ownerships.length > 0) {
          name = I18n.t("forms.labels.name") + ": " + this.ownerships[0].name;
        }
        return name;
      },
      getContactPhone: function() {
        var phone = "";
        if (this.ownerships.length > 0) {
          var firstOwnerPhone = this.ownerships[0].phone;
          if (firstOwnerPhone) {
            phone = I18n.t("forms.labels.phone") + ": " + firstOwnerPhone;
          }
        }
        return phone;
      },
      getImageUrl: function() {
        var imageUrl = IMAGE_PLACEHOLDER;
        if (this.image) {
          imageUrl = this.image.url;
        }
        return imageUrl;
      },
      translatedProducts: function(farm) {
        return _.union(farm.animal_products,
          farm.vegetable_products,
          farm.beverages).map(function(p) {
            return I18n.t('products.' + p);
          }).join(', ');
      }
    }),

    ui: {
      infoTab: "#info-tab",
      contactTab: "#contact-tab",
      membershipTab: "#membership-tab",
      infoPane: "#info",
      contactPane: "#contact",
      membershipPane: "#membership",
      placeMessageFormContainer: "#place-message-form-container",
      submitButton: ".submit"
    },

    events: {
      "click #info-tab": "onInfoTabClick",
      "click #membership-tab": "onMembershipTabClick",
      "click #contact-tab": "onContactTabClick",
      "click .call-to-action": "onMembershipPromoClick",
      "click .submit": "onSubmitClick",
      "click #edit-place": "onEditPlace"
    },

    // Override this with a schema for the actual form:
    schemata: {},

    initialize: function() {
      Teikei.vent.on("place:message:success", this.showSuccessMessage, this);
      Teikei.vent.on("place:message:failure", this.showFailureMessage, this);
    },

    onRender: function() {
      var $container = this.ui.placeMessageFormContainer;
      var ownercount = this.model.get("ownerships").length;
      var schemata = this.schemata();
      var forms = [];

      _.each(schemata, function(schema, formId) {
        var templateFile;

        if (formId !== "placeMessageForm" || (formId === "placeMessageForm" && ownercount > 0)) {
          templateFile = Marionette.Renderer.render("places/details/" + formId);
          var form = new Backbone.Form({
            model: this.model,
            schema: schema,
            template: _.template(templateFile)
          }).render();

          forms.push(form);
          form.$el.hide();
          $container.append(form.$el);
        } else {
          templateFile = Marionette.Renderer.render("places/details/placeMessageNoOwner");
          $container.append(_.template(templateFile));
        }

      }, this);

      _.defer(function() {
        forms[0].$el.show();
      });

      this.forms = forms;
      this.step = 0;
      this.bindUIElements();
    },

    onEditPlace: function(event) {
      event.preventDefault();
      Teikei.vent.trigger("edit:entry", this.model);
    },

    onSubmitClick: function(event) {
      event.preventDefault();

      var model = this.model;
      var forms = this.forms;
      var errors = forms[this.step].validate();
      var data = forms[this.step].getValue();

      if (errors === null) {
        this.hideAlertMessage(true);
        this.trigger("placeMessageForm:submit", {
          place_id: model.id,
          name: data.placeMessageName,
          email: data.placeMessageEmail,
          message: data.placeMessageMessage
        });
      }
    },

    showSuccessMessage: function(message) {
      this.showAlertMessage(message, "success");
      var form = this.forms[this.step];
      this.clearForm(form);
    },

    clearForm: function(form) {
      form.setValue("placeMessageName", "");
      form.setValue("placeMessageEmail", "");
      form.setValue("placeMessageMessage", "");
    },

    showFailureMessage: function(xhr) {
      this.showError(xhr, I18n.t("forms.messages.sending_email_failed"));
    },

    onInfoTabClick: function(event) {
      event.preventDefault();
      this.ui.infoTab.addClass("active");
      this.ui.membershipTab.removeClass("active");
      this.ui.contactTab.removeClass("active");
      this.ui.infoPane.addClass("active");
      this.ui.membershipPane.removeClass("active");
      this.ui.contactPane.removeClass("active");
    },

    onContactTabClick: function(event) {
      event.preventDefault();
      this.ui.infoTab.removeClass("active");
      this.ui.membershipTab.removeClass("active");
      this.ui.contactTab.addClass("active");
      this.ui.infoPane.removeClass("active");
      this.ui.membershipPane.removeClass("active");
      this.ui.contactPane.addClass("active");
    },

    onMembershipTabClick: function(event) {
      event.preventDefault();
      this.ui.infoTab.removeClass("active");
      this.ui.membershipTab.addClass("active");
      this.ui.contactTab.removeClass("active");
      this.ui.infoPane.removeClass("active");
      this.ui.membershipPane.addClass("active");
      this.ui.contactPane.removeClass("active");
    },

    onMembershipPromoClick: function(event) {
      this.ui.membershipTab.click();
    }
  });
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require("fs")
var glob = require("glob")
var Lexer = require("gherkin").Lexer("en");
var stringArgs

var scenarios = []

var stepsTable = {}

var current = null

var lexer = new Lexer({
    comment: function(value, line) {},
    tag: function(value, line) {},
    feature: function (keyword, name, description, line) {},
    background: function (keyword, name, description, line) {},
    scenario: function(keyword, name, description, line) {
        if (current) {
            scenarios.push(current)
        }
        current = scenario(name)
    },
    scenario_outline: function(keyword, name, description, line) {},
    examples: function(keyword, name, description, line) {},
    step: function(keyword, name, line) {
        current.steps.push(name)
        stepsTable[name] = true
    },
    doc_string: function(content_type, string, line) {},
    row: function(row, line) {},
    eof: function() {
        if (current) {
            scenarios.push(current)
        }
    }
});

function scenario(name) {
    return {
        name: name,
        steps: []
    }
}

function print(scenario) {
    console.log(
        "scenario(" + quote(scenario.name) + ", [\n    " +
            scenario.steps.map(quote).join(",\n    ") +
        "])\n")
}

function define(step) {
    console.log("scenario.define(" +
        regexify(step) +
        ",\n    function (context, assert) {\n\n\n" +

        "    })\n")
}

function quote(str) {
    return "\"" + str.replace(/\"/g, "\\\"") + "\""
}

function regexify(str) {
    return "/^" + str.replace(/\//, "\\") + "$/"
}

function printHelp() {
    var help = fs.createReadStream(ospath.join(__dirname, "scenario-build.usage.txt"))

    help.on("open", function () {
        help.pipe(process.stdout)
    })
}

function printSteps() {
     Object.keys(stepsTable).forEach(define)
}

function printScenarios() {
    scenarios.forEach(print)
}

var argv = process.argv

if (argv.length < 3 ||
    argv[2] === "-h" ||
    argv[2] === "--help") {
    printHelp()
} else {
    var processed = 0
    var i = 2

    if (argv[2] === "-s") {
        var output = printSteps
        i += 1
    } else {
        var output = printScenarios
    }

    for (; i < argv.length; i += 1) {
        processed += 1
        glob(argv[i], function build(er, files) {
            files.forEach(function (f) {
                lexer.scan(fs.readFileSync(f));
                processed -= 1
                if (processed === 0) {
                    output()
                }
            })
        })
    }
}

<commit_msg>fixed scenario-build<commit_after>#!/usr/bin/env node

var fs = require("fs")
var glob = require("glob")
var Lexer = require("gherkin").Lexer("en");
var path = require("path")

var scenarios = []

var stepsTable = {}

var current = null

var lexer = new Lexer({
    comment: function(value, line) {},
    tag: function(value, line) {},
    feature: function (keyword, name, description, line) {},
    background: function (keyword, name, description, line) {},
    scenario: function(keyword, name, description, line) {
        if (current) {
            scenarios.push(current)
        }
        current = scenario(name)
    },
    scenario_outline: function(keyword, name, description, line) {},
    examples: function(keyword, name, description, line) {},
    step: function(keyword, name, line) {
        current.steps.push(name)
        stepsTable[name] = true
    },
    doc_string: function(content_type, string, line) {},
    row: function(row, line) {},
    eof: function() {
        if (current) {
            scenarios.push(current)
        }
    }
});

function scenario(name) {
    return {
        name: name,
        steps: []
    }
}

function print(scenario) {
    console.log(
        "scenario(" + quote(scenario.name) + ", [\n    " +
            scenario.steps.map(quote).join(",\n    ") +
        "])\n")
}

function define(step) {
    console.log("scenario.define(" +
        regexify(step) +
        ",\n    function (context, assert) {\n\n\n" +

        "    })\n")
}

function quote(str) {
    return "\"" + str.replace(/\"/g, "\\\"") + "\""
}

function regexify(str) {
    return "/^" + str.replace(/\//, "\\") + "$/"
}

function printHelp() {
    var help = fs.createReadStream(path.join(__dirname, "scenario-build.usage.txt"))

    help.on("open", function () {
        help.pipe(process.stdout)
    })
}

function printSteps() {
     Object.keys(stepsTable).forEach(define)
}

function printScenarios() {
    scenarios.forEach(print)
}

var argv = process.argv

if (argv.length < 3 ||
    argv[2] === "-h" ||
    argv[2] === "--help") {
    printHelp()
} else {
    var processed = 0
    var i = 2

    if (argv[2] === "-s") {
        var output = printSteps
        i += 1
    } else {
        var output = printScenarios
    }

    for (; i < argv.length; i += 1) {
        processed += 1
        glob(argv[i], function build(er, files) {
            files.forEach(function (f) {
                lexer.scan(fs.readFileSync(f));
                processed -= 1
                if (processed === 0) {
                    output()
                }
            })
        })
    }
}

<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';
import { Router, Route, Link } from 'react-router'

class Header extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    //this.loadCarbonAds();
    //this.renderConnectedDots();
  }

  loadCarbonAds() {
    let carbonAdsContainer = this.refs.carbonAds;
    let script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = '//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=sahatyalkabovcom';
    script.id = '_carbonads_js';
    carbonAdsContainer.appendChild(script);
  }

  renderConnectedDots() {
    let canvas = this.refs.connectedDots;
    let ctx = canvas.getContext('2d');
    let colorDot = '#fff';
    let color = '#fff';

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.display = 'block';
    ctx.fillStyle = colorDot;
    ctx.lineWidth = .1;
    ctx.strokeStyle = color;

    var mousePosition = {
      x: 30 * canvas.width / 100,
      y: 30 * canvas.height / 100
    };

    var dots = {
      nb: 350,
      distance: 60,
      d_radius: 100,
      array: []
    };

    function Dot() {
      this.x = Math.random() * canvas.width;
      this.y = Math.random() * canvas.height;

      this.vx = -.5 + Math.random();
      this.vy = -.5 + Math.random();

      this.radius = Math.random();
    }

    Dot.prototype = {
      create: function() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
        ctx.fill();
      },

      animate: function() {

        for (let i = 0; i < dots.nb; i++) {

          var dot = dots.array[i];

          if (dot.y < 0 || dot.y > canvas.height) {
            dot.vx = dot.vx;
            dot.vy = -dot.vy;
          }
          else if (dot.x < 0 || dot.x > canvas.width) {
            dot.vx = -dot.vx;
            dot.vy = dot.vy;
          }
          dot.x += dot.vx;
          dot.y += dot.vy;
        }
      },

      line: function() {
        for (let i = 0; i < dots.nb; i++) {
          for (let j = 0; j < dots.nb; j++) {
            var i_dot = dots.array[i];
            var j_dot = dots.array[j];

            if ((i_dot.x - j_dot.x) < dots.distance && (i_dot.y - j_dot.y) < dots.distance && (i_dot.x - j_dot.x) > -dots.distance && (i_dot.y - j_dot.y) > -dots.distance) {
              if ((i_dot.x - mousePosition.x) < dots.d_radius && (i_dot.y - mousePosition.y) < dots.d_radius && (i_dot.x - mousePosition.x) > -dots.d_radius && (i_dot.y - mousePosition.y) > -dots.d_radius) {
                ctx.beginPath();
                ctx.moveTo(i_dot.x, i_dot.y);
                ctx.lineTo(j_dot.x, j_dot.y);
                ctx.stroke();
                ctx.closePath();
              }
            }
          }
        }
      }
    };

    function createDots() {
      let dot;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (let i = 0; i < dots.nb; i++) {
        dots.array.push(new Dot());
        dot = dots.array[i];

        dot.create();
      }

      dot.line();
      dot.animate();
    }

    window.onmousemove = function(parameter) {
      mousePosition.x = parameter.pageX;
      mousePosition.y = parameter.pageY;
    };

    mousePosition.x = window.innerWidth / 2;
    mousePosition.y = window.innerHeight / 2;

    setInterval(createDots, 1000 / 30);
  }

  render() {
    return (

        <canvas ref="connectedDots"/>

Report a bug

Contributing

Mega Boilerplate

            Simple and easy to use hand-crafted starter kits.

Demo 1

Demo 2

Demo 3

            Don't forget to  on GitHub if you liked this project!

    );
  }
}

export default Header;
<commit_msg>Updated header title for reporting issues<commit_after>import React from 'react';
import cx from 'classnames';
import { Router, Route, Link } from 'react-router'

class Header extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    //this.loadCarbonAds();
    //this.renderConnectedDots();
  }

  loadCarbonAds() {
    let carbonAdsContainer = this.refs.carbonAds;
    let script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = '//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=sahatyalkabovcom';
    script.id = '_carbonads_js';
    carbonAdsContainer.appendChild(script);
  }

  renderConnectedDots() {
    let canvas = this.refs.connectedDots;
    let ctx = canvas.getContext('2d');
    let colorDot = '#fff';
    let color = '#fff';

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.display = 'block';
    ctx.fillStyle = colorDot;
    ctx.lineWidth = .1;
    ctx.strokeStyle = color;

    var mousePosition = {
      x: 30 * canvas.width / 100,
      y: 30 * canvas.height / 100
    };

    var dots = {
      nb: 350,
      distance: 60,
      d_radius: 100,
      array: []
    };

    function Dot() {
      this.x = Math.random() * canvas.width;
      this.y = Math.random() * canvas.height;

      this.vx = -.5 + Math.random();
      this.vy = -.5 + Math.random();

      this.radius = Math.random();
    }

    Dot.prototype = {
      create: function() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
        ctx.fill();
      },

      animate: function() {

        for (let i = 0; i < dots.nb; i++) {

          var dot = dots.array[i];

          if (dot.y < 0 || dot.y > canvas.height) {
            dot.vx = dot.vx;
            dot.vy = -dot.vy;
          }
          else if (dot.x < 0 || dot.x > canvas.width) {
            dot.vx = -dot.vx;
            dot.vy = dot.vy;
          }
          dot.x += dot.vx;
          dot.y += dot.vy;
        }
      },

      line: function() {
        for (let i = 0; i < dots.nb; i++) {
          for (let j = 0; j < dots.nb; j++) {
            var i_dot = dots.array[i];
            var j_dot = dots.array[j];

            if ((i_dot.x - j_dot.x) < dots.distance && (i_dot.y - j_dot.y) < dots.distance && (i_dot.x - j_dot.x) > -dots.distance && (i_dot.y - j_dot.y) > -dots.distance) {
              if ((i_dot.x - mousePosition.x) < dots.d_radius && (i_dot.y - mousePosition.y) < dots.d_radius && (i_dot.x - mousePosition.x) > -dots.d_radius && (i_dot.y - mousePosition.y) > -dots.d_radius) {
                ctx.beginPath();
                ctx.moveTo(i_dot.x, i_dot.y);
                ctx.lineTo(j_dot.x, j_dot.y);
                ctx.stroke();
                ctx.closePath();
              }
            }
          }
        }
      }
    };

    function createDots() {
      let dot;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (let i = 0; i < dots.nb; i++) {
        dots.array.push(new Dot());
        dot = dots.array[i];

        dot.create();
      }

      dot.line();
      dot.animate();
    }

    window.onmousemove = function(parameter) {
      mousePosition.x = parameter.pageX;
      mousePosition.y = parameter.pageY;
    };

    mousePosition.x = window.innerWidth / 2;
    mousePosition.y = window.innerHeight / 2;

    setInterval(createDots, 1000 / 30);
  }

  render() {
    return (

        <canvas ref="connectedDots"/>

Report Issues

Contributing

Mega Boilerplate

            Simple and easy to use hand-crafted starter kits.

Demo 1

Demo 2

Demo 3

            Don't forget to  on GitHub if you liked this project!

    );
  }
}

export default Header;
<|endoftext|>


<commit_before>var h = require('hyperscript')
var u = require('../util')
var pull = require('pull-stream')

var plugs = require('../plugs')
var message_content = plugs.first(exports.message_content = [])
var message_content_mini = plugs.first(exports.message_content_mini = [])
var avatar = plugs.first(exports.avatar = [])
var avatar_name = plugs.first(exports.avatar_name = [])
var avatar_link = plugs.first(exports.avatar_link = [])
var message_meta = plugs.map(exports.message_meta = [])
var message_action = plugs.map(exports.message_action = [])
var message_link = plugs.first(exports.message_link = [])

var sbot_links = plugs.first(exports.sbot_links = [])

exports.message_render = function (msg, sbot) {
  var elMini = message_content_mini(msg)
  if (elMini) {
    var div = h('div.message.message--mini',
      h('div.row',
        h('div',
          avatar_link(msg.value.author, avatar_name(msg.value.author)),
          h('span.message_content', elMini)),
        h('div.message_meta.row', message_meta(msg))
      )
    )
    div.setAttribute('tabindex', '0')
    return div
  }

  var el = message_content(msg)
  if(!el) return

  var links = []
  for(var k in CACHE) {
    var _msg = CACHE[k]
    if(Array.isArray(_msg.content.mentions)) {
      for(var i = 0; i < _msg.content.mentions.length; i++)
        if(_msg.content.mentions[i].link == msg.key)
        links.push(k)
    }
  }

  var backlinks = h('div.backlinks')
  if(links.length)
    backlinks.appendChild(h('label', 'backlinks:',
      h('div', links.map(function (key) {
        return message_link(key)
      }))
    ))

//  pull(
//    sbot_links({dest: msg.key, rel: 'mentions', keys: true}),
//    pull.collect(function (err, links) {
//      if(links.length)
//        backlinks.appendChild(h('label', 'backlinks:',
//          h('div', links.map(function (link) {
//            return message_link(link.key)
//          }))
//        ))
//    })
//  )

  var msg = h('div.message',
    h('div.title.row',
      h('div.avatar', avatar(msg.value.author, 'thumbnail')),
      h('div.message_meta.row', message_meta(msg))
    ),
    h('div.message_content', el),
    h('div.message_actions.row',
      h('div.actions', message_action(msg),
        h('a', {href: '#' + msg.key}, 'Reply')
      )
    ),
    backlinks,
    {onkeydown: function (ev) {
      //on enter, hit first meta.
      if(ev.keyCode == 13) {

        // unless in an input
        if (ev.target.nodeName === 'INPUT'
          || ev.target.nodeName === 'TEXTAREA') return

        msg.querySelector('.enter').click()
      }
    }}
  )

  // ); hyperscript does not seem to set attributes correctly.
  msg.setAttribute('tabindex', '0')

  return msg
}

<commit_msg>Add fallback message renderer<commit_after>var h = require('hyperscript')
var u = require('../util')
var pull = require('pull-stream')

var plugs = require('../plugs')
var message_content = plugs.first(exports.message_content = [])
var message_content_mini = plugs.first(exports.message_content_mini = [])
var avatar = plugs.first(exports.avatar = [])
var avatar_name = plugs.first(exports.avatar_name = [])
var avatar_link = plugs.first(exports.avatar_link = [])
var message_meta = plugs.map(exports.message_meta = [])
var message_action = plugs.map(exports.message_action = [])
var message_link = plugs.first(exports.message_link = [])

var sbot_links = plugs.first(exports.sbot_links = [])

function mini(msg, el) {
  var div = h('div.message.message--mini',
    h('div.row',
      h('div',
        avatar_link(msg.value.author, avatar_name(msg.value.author)),
        h('span.message_content', el)),
      h('div.message_meta.row', message_meta(msg))
    )
  )
  div.setAttribute('tabindex', '0')
  return div
}

function message_content_mini_fallback(msg)  {
  return h('code', msg.value.content.type)
}

exports.message_render = function (msg, sbot) {
  var el = message_content_mini(msg)
  if(el) return mini(msg, el)

  var el = message_content(msg)
  if(!el) return mini(msg, message_content_mini_fallback(msg))

  var links = []
  for(var k in CACHE) {
    var _msg = CACHE[k]
    if(Array.isArray(_msg.content.mentions)) {
      for(var i = 0; i < _msg.content.mentions.length; i++)
        if(_msg.content.mentions[i].link == msg.key)
        links.push(k)
    }
  }

  var backlinks = h('div.backlinks')
  if(links.length)
    backlinks.appendChild(h('label', 'backlinks:',
      h('div', links.map(function (key) {
        return message_link(key)
      }))
    ))

//  pull(
//    sbot_links({dest: msg.key, rel: 'mentions', keys: true}),
//    pull.collect(function (err, links) {
//      if(links.length)
//        backlinks.appendChild(h('label', 'backlinks:',
//          h('div', links.map(function (link) {
//            return message_link(link.key)
//          }))
//        ))
//    })
//  )

  var msg = h('div.message',
    h('div.title.row',
      h('div.avatar', avatar(msg.value.author, 'thumbnail')),
      h('div.message_meta.row', message_meta(msg))
    ),
    h('div.message_content', el),
    h('div.message_actions.row',
      h('div.actions', message_action(msg),
        h('a', {href: '#' + msg.key}, 'Reply')
      )
    ),
    backlinks,
    {onkeydown: function (ev) {
      //on enter, hit first meta.
      if(ev.keyCode == 13) {

        // unless in an input
        if (ev.target.nodeName === 'INPUT'
          || ev.target.nodeName === 'TEXTAREA') return

        msg.querySelector('.enter').click()
      }
    }}
  )

  // ); hyperscript does not seem to set attributes correctly.
  msg.setAttribute('tabindex', '0')

  return msg
}

<|endoftext|>


<commit_before>M.wrap('github/jillix/editor/v0.0.1/editor.js', function (require, module, exports) {

var Bind = require('github/jillix/bind/v0.0.1/bind');

var statusText = [
    /*0*/
    "Document has changed",
    /*1*/
    "Document is saving...",
    /*2*/
    "All changes saved",
    /*3*/
    "An Error occurred while saving, please try again",
    /*4*/
    "Your changes are not saved!",
    /*5*/
    "Please wait till document is saved!",
    /*6*/
    "Document is loading..."
];

function setupAce () {
    var self = this;

    self.editor = ace.edit("aceEdit");
    self.session = self.editor.getSession();
    self.changed = 0;
    self.saving = false;

    //setup editor
    self.editor.setTheme("ace/theme/textmate");

    // set font size
    self.editor.setFontSize(13);

    //add ctrl-s command
    self.editor.commands.addCommand({

        name: "save",
        bindKey: {

            win: "Ctrl-S",
            mac: "Command-S",
            sender: "editor"
        },
        exec: function () {
            saveDocument.call(self);
        }
    });

    // save automatically after 1s, if doc has changed
    //var interval;
    self.session.on("change", function() {

        self.changed = 1;
        self.info.innerHTML = statusText[0];

        /*if (!interval) {
            interval = setTimeout(function () {
                interval = null;
                saveDocument.call(self);
            }, 1000);
        }*/
    });
}

function saveDocument() {
    var self = this;

    if(self.changed === 1 && !self.saving) {

        self.saving = true;
        self.changed = 2;
        self.info.innerHTML = statusText[1];

        // TODO save data to db
        /*request("save/" + docName, self.editor.getValue(), function(err) {

            if (err) {

                self.changed = 1;
                self.info.innerHTML = statusText[3];
            }
            else if (self.changed == 2) {

                self.changed = 0;
                self.info.innerHTML = statusText[2];
            }

            self.saving = false;
        });*/

        self.changed = 0;
        self.info.innerHTML = statusText[2];
        self.saving = false;
    }
}

function load () {
    var self = this;
    if (self.session) {

        // set mode
        self.session.setMode("ace/mode/json");

        self.info.innerHTML = statusText[6];

        // TODO load data into editor
        self.session.setValue('{\n\t"json": "editor"\n}\n');

        self.info.innerHTML = statusText[2];
    }
}

function init () {
    var self = this;
    self.load = load;
    config = self.mono.config.data;

    // init bind
    Bind(self).load(config.bind, function (err, bind) {

        if (err) {
            // TODO do something on error
            return;
        }

        // save bind instance
        self.bind = bind;

        // set an empty state is the same like: state.set(location.pathname);
        bind.view.render();

        // get info field dom ref
        if (config.info) {
            self.info = bind.view.dom.querySelector(config.info);
        }

        // get save button dom ref
        if (config.save) {
            self.save = bind.view.dom.querySelector(config.save);
            if(self.save) {
                self.save.addEventListener('click', function () {
                    saveDocument.call(self);
                }, false);
            }
        }

        // setup the ace editor
        setupAce.call(self);

        // init state
        bind.state.emit();

        self.emit('ready');
    });
}

module.exports = init;

return module;

});
<commit_msg>test ace editor<commit_after>M.wrap('github/jillix/editor/v0.0.1/editor.js', function (require, module, exports) {

// TODO warn when window closes and unsaved changes exists

var Bind = require('github/jillix/bind/v0.0.1/bind');

var statusText = [
    /*0*/
    "Document has changed",
    /*1*/
    "Document is saving...",
    /*2*/
    "All changes saved",
    /*3*/
    "An Error occurred while saving, please try again",
    /*4*/
    "Your changes are not saved!",
    /*5*/
    "Please wait till document is saved!",
    /*6*/
    "Document is loading..."
];

function setupAce () {
    var self = this;

    self.editor = ace.edit("aceEdit");
    self.session = self.editor.getSession();
    self.changed = 0;
    self.saving = false;

    //setup editor
    self.editor.setTheme("ace/theme/textmate");

    // set font size
    self.editor.setFontSize(13);

    //add ctrl-s command
    self.editor.commands.addCommand({

        name: "save",
        bindKey: {

            win: "Ctrl-S",
            mac: "Command-S",
            sender: "editor"
        },
        exec: function () {
            saveDocument.call(self);
        }
    });

    // save automatically after 1s, if doc has changed
    self.session.on("change", function() {
        self.changed = 1;
        self.info.innerHTML = statusText[0];
    });
}

function saveDocument() {
    var self = this;

    if(self.changed === 1 && !self.saving) {

        self.saving = true;
        self.changed = 2;
        self.info.innerHTML = statusText[1];

        // TODO save data to db
        /*request("save/" + docName, self.editor.getValue(), function(err) {

            if (err) {

                self.changed = 1;
                self.info.innerHTML = statusText[3];
            }
            else if (self.changed == 2) {

                self.changed = 0;
                self.info.innerHTML = statusText[2];
            }

            self.saving = false;
        });*/

        self.changed = 0;
        self.info.innerHTML = statusText[2];
        self.saving = false;
    }
}

function load () {
    var self = this;
    if (self.session) {

        // set mode
        self.session.setMode("ace/mode/json");

        // set status text
        self.info.innerHTML = statusText[6];

        var path = location.pathname.split('/');
        var template = path[2];
        var item = path[3];

        // TODO load data from db into editor
        self.session.setValue('{\n\t"template": "' + template + '",\n\t"item": "' + item + '"\n}\n');

        // set status text
        self.info.innerHTML = statusText[2];
    }
}

function init () {
    var self = this;
    self.load = load;
    config = self.mono.config.data;

    // init bind
    Bind(self).load(config.bind, function (err, bind) {

        if (err) {
            return;
        }

        // save bind instance
        self.bind = bind;

        // set an empty state is the same like: state.set(location.pathname);
        bind.view.render();

        // get info field dom ref
        if (config.info) {
            self.info = bind.view.dom.querySelector(config.info);
        }

        // get save button dom ref
        if (config.save) {
            self.save = bind.view.dom.querySelector(config.save);
            if(self.save) {
                self.save.addEventListener('click', function () {
                    saveDocument.call(self);
                }, false);
            }
        }

        // setup the ace editor
        setupAce.call(self);

        // init state
        bind.state.emit();

        self.emit('ready');
    });
}

module.exports = init;

return module;

});
<|endoftext|>


<commit_before>var Surveyable = function(){

  var self = this, drawGraph, barRequired, lineRequired;

  barRequired = {
    xkey: 'answer_text',
    ykeys: ['answer_occurrence'],
    labels: ['Answer Occurrence'],
    xLabelAngle: 35
  }

  lineRequired = {
    xkey: 'answer_text',
    ykeys: ['answer_occurrence'],
    labels: ['Answer Occurrence'],
    parseTime: false
  }

  drawGraph = function(type, data, $element, options){
    var defaults = {
      element: $element,
      data: data
    }
    var finalOptions = $.extend(defaults, options);
    var graph = new Morris[type](finalOptions);
  }

  this.checkBoxFieldGraph = function(data, $element){
    var outOptions = $.extend(self.checkBoxFieldGraphOptions, barRequired)

    drawGraph("Bar", data, $element, outOptions);
  }

  this.selectFieldGraph = function(data, $element){
    var outOptions = $.extend(self.selectFieldGraphOptions, barRequired)

    drawGraph("Bar", data, $element, outOptions);
  }

  this.rankFieldGraph = function(data, $element){
    var outOptions = $.extend(self.rankFieldGraphOptions, lineRequired)

    drawGraph("Line", data, $element, outOptions);
  }

  this.radioButtonFieldGraph = function(data, $element){
    var outData = $.map(data, function(answer, index){
      return { value: answer.answer_occurrence, label: answer.answer_text };
    });

    drawGraph("Donut", outData, $element, self.radioButtonFieldGraphOptions);
  }

  return self;
}

var Surveyable = Surveyable();

$(document).ready(function(){
  var $reportableQuestion = $(".reportable_question");

  if ($reportableQuestion.length > 0){
    $reportableQuestion.each(function( index ){
      var $element = $(this).closest('.question').find('.graph');

      $.ajax({
        url: "/surveyable/questions/"+$(this).val()+"/reports",
        dataType: "json",
        success: function(results){
          if (results.field_type == "check_box_field") {
            Surveyable.checkBoxFieldGraph(results.answers, $element);

          } else if (results.field_type == "rank_field") {
            Surveyable.rankFieldGraph(results.answers, $element);

          } else if (results.field_type == "radio_button_field") {
            Surveyable.radioButtonFieldGraph(results.answers, $element);

          } else if (results.field_type == "select_field") {
            Surveyable.selectFieldGraph(results.answers, $element);

          }
        }
      });
    });
  }
});

<commit_msg>As per bernardeli's comment<commit_after>var SurveyableMaster = function(){

  var self = this, drawGraph, barRequired, lineRequired;

  barRequired = {
    xkey: 'answer_text',
    ykeys: ['answer_occurrence'],
    labels: ['Answer Occurrence'],
    xLabelAngle: 35
  }

  lineRequired = {
    xkey: 'answer_text',
    ykeys: ['answer_occurrence'],
    labels: ['Answer Occurrence'],
    parseTime: false
  }

  drawGraph = function(type, data, $element, options){
    var defaults = {
      element: $element,
      data: data
    }
    var finalOptions = $.extend(defaults, options);
    var graph = new Morris[type](finalOptions);
  }

  this.checkBoxFieldGraph = function(data, $element){
    var outOptions = $.extend(self.checkBoxFieldGraphOptions, barRequired)

    drawGraph("Bar", data, $element, outOptions);
  }

  this.selectFieldGraph = function(data, $element){
    var outOptions = $.extend(self.selectFieldGraphOptions, barRequired)

    drawGraph("Bar", data, $element, outOptions);
  }

  this.rankFieldGraph = function(data, $element){
    var outOptions = $.extend(self.rankFieldGraphOptions, lineRequired)

    drawGraph("Line", data, $element, outOptions);
  }

  this.radioButtonFieldGraph = function(data, $element){
    var outData = $.map(data, function(answer, index){
      return { value: answer.answer_occurrence, label: answer.answer_text };
    });

    drawGraph("Donut", outData, $element, self.radioButtonFieldGraphOptions);
  }

  this.report = function(data, $element) {
    if (data.field_type == "check_box_field") {
      self.checkBoxFieldGraph(data.answers, $element);

    } else if (data.field_type == "rank_field") {
      self.rankFieldGraph(data.answers, $element);

    } else if (data.field_type == "radio_button_field") {
      self.radioButtonFieldGraph(data.answers, $element);

    } else if (data.field_type == "select_field") {
      self.selectFieldGraph(data.answers, $element);

    }
  }

  return self;
}

var Surveyable = SurveyableMaster();

$(document).ready(function(){
  var $reportableQuestion = $(".reportable_question");

  if ($reportableQuestion.length > 0){
    $reportableQuestion.each(function( index ){
      var $element = $(this).closest('.question').find('.graph');

      $.ajax({
        url: "/surveyable/questions/"+$(this).val()+"/reports",
        dataType: "json",
        success: function(results){
          Surveyable.report(results, $element);
        }
      });
    });
  }
});

<|endoftext|>


<commit_before>/*global window, document, setTimeout, Ghost, $, _, Backbone, JST, shortcut */
(function () {
    "use strict";

    Ghost.TemplateView = Backbone.View.extend({
        templateName: "widget",

        template: function (data) {
            return JST[this.templateName](data);
        },

        templateData: function () {
            if (this.model) {
                return this.model.toJSON();
            }

            if (this.collection) {
                return this.collection.toJSON();
            }

            return {};
        },

        render: function () {
            if (_.isFunction(this.beforeRender)) {
                this.beforeRender();
            }

            this.$el.html(this.template(this.templateData()));

            if (_.isFunction(this.afterRender)) {
                this.afterRender();
            }

            return this;
        }
    });

    Ghost.View = Ghost.TemplateView.extend({

        // Adds a subview to the current view, which will
        // ensure its removal when this view is removed,
        // or when view.removeSubviews is called
        addSubview: function (view) {
            if (!(view instanceof Backbone.View)) {
                throw new Error("Subview must be a Backbone.View");
            }
            this.subviews = this.subviews || [];
            this.subviews.push(view);
            return view;
        },

        // Removes any subviews associated with this view
        // by `addSubview`, which will in-turn remove any
        // children of those views, and so on.
        removeSubviews: function () {
            var children = this.subviews;

            if (!children) {
                return this;
            }

            _(children).invoke("remove");

            this.subviews = [];
            return this;
        },

        // Extends the view's remove, by calling `removeSubviews`
        // if any subviews exist.
        remove: function () {
            if (this.subviews) {
                this.removeSubviews();
            }
            return Backbone.View.prototype.remove.apply(this, arguments);
        }
    });

    Ghost.Views.Utils = {

        // Used in API request fail handlers to parse a standard api error
        // response json for the message to display
        getRequestErrorMessage: function (request) {
            var message,
                msgDetail;

            // Can't really continue without a request
            if (!request) {
                return null;
            }

            // Seems like a sensible default
            message = request.statusText;

            // If a non 200 response
            if (request.status !== 200) {
                try {
                    // Try to parse out the error, or default to "Unknown"
                    message =  request.responseJSON.error || "Unknown Error";
                } catch (e) {
                    msgDetail = request.status ? request.status + " - " + request.statusText : "Server was not available";
                    message = "The server returned an error (" + msgDetail + ").";
                }
            }

            return message;
        },

        // Getting URL vars
        getUrlVariables: function () {
            var vars = [],
                hash,
                hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'),
                i;

            for (i = 0; i < hashes.length; i += 1) {
                hash = hashes[i].split('=');
                vars.push(hash[0]);
                vars[hash[0]] = hash[1];
            }
            return vars;
        }
    };

    /**
     * This is the view to generate the markup for the individual
     * notification. Will be included into #notifications.
     *
     * States can be
     * - persistent
     * - passive
     *
     * Types can be
     * - error
     * - success
     * - alert
     * -   (empty)
     *
     */
    Ghost.Views.Notification = Ghost.View.extend({
        templateName: 'notification',
        className: 'js-bb-notification',
        template: function (data) {
            return JST[this.templateName](data);
        },
        render: function () {
            var html = this.template(this.model);
            this.$el.html(html);
            return this;
        }
    });

    /**
     * This handles Notification groups
     */
    Ghost.Views.NotificationCollection = Ghost.View.extend({
        el: '#notifications',
        initialize: function () {
            var self = this;
            this.render();
            Ghost.on('urlchange', function () {
                self.clearEverything();
            });
        },
        events: {
            'animationend .js-notification': 'removeItem',
            'webkitAnimationEnd .js-notification': 'removeItem',
            'oanimationend .js-notification': 'removeItem',
            'MSAnimationEnd .js-notification': 'removeItem',
            'click .js-notification.notification-passive .close': 'closePassive',
            'click .js-notification.notification-persistent .close': 'closePersistent'
        },
        render: function () {
            _.each(this.model, function (item) {
                this.renderItem(item);
            }, this);
        },
        renderItem: function (item) {
            var itemView = new Ghost.Views.Notification({ model: item }),
                height,
                self = this;
            this.$el.html(itemView.render().el).css({height: 0});
            height = this.$('.js-notification').hide().outerHeight(true);
            this.$el.animate({height: height}, 250, function () {
                $(this).css({height: "auto"});
                self.$('.js-notification').fadeIn(250);
            });
        },
        addItem: function (item) {
            this.model.push(item);
            this.renderItem(item);
        },
        clearEverything: function () {
            var height = this.$('.js-notification').outerHeight(true),
                self = this;
            this.$el.css({height: height});
            this.$el.find('.js-notification.notification-passive').fadeOut(250,  function () {
                $(this).remove();
                self.$el.slideUp(250, function () {
                    $(this).show().css({height: "auto"});
                });
            });
        },
        removeItem: function (e) {
            e.preventDefault();
            var self = e.currentTarget,
                bbSelf = this;
            if (self.className.indexOf('notification-persistent') !== -1) {
                $.ajax({
                    type: "DELETE",
                    url: '/api/v0.1/notifications/' + $(self).find('.close').data('id')
                }).done(function (result) {
                    bbSelf.$el.slideUp(250, function () {
                        $(this).show().css({height: "auto"});
                        $(self).remove();
                    });
                });
            } else {
                this.$el.slideUp(250, function () {
                    $(this).show().css({height: "auto"});
                    $(self).remove();
                });
            }

        },
        closePassive: function (e) {
            var height = this.$('.js-notification').outerHeight(true),
                self = this;
            this.$el.css({height: height});
            $(e.currentTarget).parent().fadeOut(250,  function () {
                $(this).remove();
                self.$el.slideUp(250, function () {
                    $(this).show().css({height: "auto"});
                });
            });
        },
        closePersistent: function (e) {
            var self = e.currentTarget,
                bbSelf = this;
            $.ajax({
                type: "DELETE",
                url: '/api/v0.1/notifications/' + $(self).data('id')
            }).done(function (result) {
                var height = bbSelf.$('.js-notification').outerHeight(true),
                    $parent = $(self).parent();
                bbSelf.$el.css({height: height});

                if ($parent.parent().hasClass('js-bb-notification')) {
                    $parent.parent().fadeOut(200,  function () {
                        $(this).remove();
                        bbSelf.$el.slideUp(250, function () {
                            $(this).show().css({height: "auto"});
                        });
                    });
                } else {
                    $parent.fadeOut(200,  function () {
                        $(this).remove();
                        bbSelf.$el.slideUp(250, function () {
                            $(this).show().css({height: "auto"});
                        });
                    });
                }
            });
        }
    });

    // ## Modals
    Ghost.Views.Modal = Ghost.View.extend({
        el: '#modal-container',
        templateName: 'modal',
        className: 'js-bb-modal',
        // Render and manages modal dismissal
        initialize: function () {
            this.render();
            var self = this;
            if (!this.model.options.confirm) {
                shortcut.add("ESC", function () {
                    self.removeElement();
                });
                $(document).on('click', '.modal-background', function (e) {
                    self.removeElement(e);
                });
            } else {
                // Initiate functions for buttons here so models don't get tied up.
                this.acceptModal = function () {
                    this.model.options.confirm.accept.func.call(this);
                    self.removeElement();
                };
                this.rejectModal = function () {
                    this.model.options.confirm.reject.func.call(this);
                    self.removeElement();
                };
                shortcut.remove("ESC");
                $(document).off('click', '.modal-background');
            }
        },
        templateData: function () {
            return this.model;
        },
        events: {
            'click .close': 'removeElement',
            'click .js-button-accept': 'acceptModal',
            'click .js-button-reject': 'rejectModal'
        },
        afterRender: function () {
            this.$(".modal-content").html(this.addSubview(new Ghost.Views.Modal.ContentView({model: this.model})).render().el);
            this.$el.children(".js-modal").center({animate: false}).css("max-height", $(window).height() - 120); // same as resize(), but the debounce causes init lag
            this.$el.addClass("active dark");

            if (document.body.style.webkitFilter !== undefined) { // Detect webkit filters
                $("body").addClass("blur");
            }
            if (_.isFunction(this.model.options.afterRender)) {
                this.model.options.afterRender.call(this);
            }
            if (this.model.options.animation) {
                this.animate(this.$el.children(".js-modal"));
            }
            var self = this;
            $(window).on('resize', self.resize);

        },
        // #### resize
        // Center and resize modal based on window height
        resize: _.debounce(function () {
            $(".js-modal").center().css("max-height", $(window).height() - 120);
        }, 50),
        // #### remove
        // Removes Backbone attachments from modals
        remove: function () {
            this.undelegateEvents();
            this.$el.empty();
            this.stopListening();
            return this;
        },
        // #### removeElement
        // Visually removes the modal from the user interface
        removeElement: function (e) {
            if (e) {
                e.preventDefault();
                e.stopPropagation();
            }

            var self = this,
                $jsModal = $('.js-modal'),
                removeModalDelay = $jsModal.transitionDuration(),
                removeBackgroundDelay = self.$el.transitionDuration();

            $jsModal.removeClass('in');

            if (!this.model.options.animation) {
                removeModalDelay = removeBackgroundDelay = 0;
            }

            setTimeout(function () {

                if (document.body.style.filter !== undefined) {
                    $("body").removeClass("blur");
                }
                self.$el.removeClass('dark');

                setTimeout(function () {
                    self.remove();
                    self.$el.removeClass('active');
                }, removeBackgroundDelay);
            }, removeModalDelay);

        },
        // #### animate
        // Animates the animation
        animate: function (target) {
            setTimeout(function () {
                target.addClass('in');
            }, target.transitionDuration());
        }
    });

    // ## Modal Content
    Ghost.Views.Modal.ContentView = Ghost.View.extend({

        template: function (data) {
            return JST['modals/' + this.model.content.template](data);
        },
        templateData: function () {
            return this.model;
        }

    });
}());
<commit_msg>Ability to spawn multiple notifications<commit_after>/*global window, document, setTimeout, Ghost, $, _, Backbone, JST, shortcut */
(function () {
    "use strict";

    Ghost.TemplateView = Backbone.View.extend({
        templateName: "widget",

        template: function (data) {
            return JST[this.templateName](data);
        },

        templateData: function () {
            if (this.model) {
                return this.model.toJSON();
            }

            if (this.collection) {
                return this.collection.toJSON();
            }

            return {};
        },

        render: function () {
            if (_.isFunction(this.beforeRender)) {
                this.beforeRender();
            }

            this.$el.html(this.template(this.templateData()));

            if (_.isFunction(this.afterRender)) {
                this.afterRender();
            }

            return this;
        }
    });

    Ghost.View = Ghost.TemplateView.extend({

        // Adds a subview to the current view, which will
        // ensure its removal when this view is removed,
        // or when view.removeSubviews is called
        addSubview: function (view) {
            if (!(view instanceof Backbone.View)) {
                throw new Error("Subview must be a Backbone.View");
            }
            this.subviews = this.subviews || [];
            this.subviews.push(view);
            return view;
        },

        // Removes any subviews associated with this view
        // by `addSubview`, which will in-turn remove any
        // children of those views, and so on.
        removeSubviews: function () {
            var children = this.subviews;

            if (!children) {
                return this;
            }

            _(children).invoke("remove");

            this.subviews = [];
            return this;
        },

        // Extends the view's remove, by calling `removeSubviews`
        // if any subviews exist.
        remove: function () {
            if (this.subviews) {
                this.removeSubviews();
            }
            return Backbone.View.prototype.remove.apply(this, arguments);
        }
    });

    Ghost.Views.Utils = {

        // Used in API request fail handlers to parse a standard api error
        // response json for the message to display
        getRequestErrorMessage: function (request) {
            var message,
                msgDetail;

            // Can't really continue without a request
            if (!request) {
                return null;
            }

            // Seems like a sensible default
            message = request.statusText;

            // If a non 200 response
            if (request.status !== 200) {
                try {
                    // Try to parse out the error, or default to "Unknown"
                    message =  request.responseJSON.error || "Unknown Error";
                } catch (e) {
                    msgDetail = request.status ? request.status + " - " + request.statusText : "Server was not available";
                    message = "The server returned an error (" + msgDetail + ").";
                }
            }

            return message;
        },

        // Getting URL vars
        getUrlVariables: function () {
            var vars = [],
                hash,
                hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'),
                i;

            for (i = 0; i < hashes.length; i += 1) {
                hash = hashes[i].split('=');
                vars.push(hash[0]);
                vars[hash[0]] = hash[1];
            }
            return vars;
        }
    };

    /**
     * This is the view to generate the markup for the individual
     * notification. Will be included into #notifications.
     *
     * States can be
     * - persistent
     * - passive
     *
     * Types can be
     * - error
     * - success
     * - alert
     * -   (empty)
     *
     */
    Ghost.Views.Notification = Ghost.View.extend({
        templateName: 'notification',
        className: 'js-bb-notification',
        template: function (data) {
            return JST[this.templateName](data);
        },
        render: function () {
            var html = this.template(this.model);
            this.$el.html(html);
            return this;
        }
    });

    /**
     * This handles Notification groups
     */
    Ghost.Views.NotificationCollection = Ghost.View.extend({
        el: '#notifications',
        initialize: function () {
            var self = this;
            this.render();
            Ghost.on('urlchange', function () {
                self.clearEverything();
            });
        },
        events: {
            'animationend .js-notification': 'removeItem',
            'webkitAnimationEnd .js-notification': 'removeItem',
            'oanimationend .js-notification': 'removeItem',
            'MSAnimationEnd .js-notification': 'removeItem',
            'click .js-notification.notification-passive .close': 'closePassive',
            'click .js-notification.notification-persistent .close': 'closePersistent'
        },
        render: function () {
            _.each(this.model, function (item) {
                this.renderItem(item);
            }, this);
        },
        renderItem: function (item) {
            var itemView = new Ghost.Views.Notification({ model: item }),
                height,
                $notification = $(itemView.render().el);

            this.$el.append($notification);
            height = $notification.hide().outerHeight(true);
            $notification.animate({height: height}, 250, function () {
                $(this)
                    .css({height: "auto"})
                    .fadeIn(250);
            });
        },
        addItem: function (item) {
            this.model.push(item);
            this.renderItem(item);
        },
        clearEverything: function () {
            var height = this.$('.js-notification').outerHeight(true),
                self = this;
            this.$el.css({height: height});
            this.$el.find('.js-notification.notification-passive').fadeOut(250,  function () {
                $(this).remove();
                self.$el.slideUp(250, function () {
                    $(this).show().css({height: "auto"});
                });
            });
        },
        removeItem: function (e) {
            e.preventDefault();
            var self = e.currentTarget,
                bbSelf = this;
            if (self.className.indexOf('notification-persistent') !== -1) {
                $.ajax({
                    type: "DELETE",
                    url: '/api/v0.1/notifications/' + $(self).find('.close').data('id')
                }).done(function (result) {
                    bbSelf.$el.slideUp(250, function () {
                        $(this).show().css({height: "auto"});
                        $(self).remove();
                    });
                });
            } else {
                $(self).slideUp(250, function () {
                    $(this)
                        .show()
                        .css({height: "auto"})
                        .remove();
                });
            }
        },
        closePassive: function (e) {
            $(e.currentTarget)
                .parent()
                .fadeOut(250)
                .slideUp(250, function () {
                    $(this).remove();
                });
        },
        closePersistent: function (e) {
            var self = e.currentTarget,
                bbSelf = this;
            $.ajax({
                type: "DELETE",
                url: '/api/v0.1/notifications/' + $(self).data('id')
            }).done(function (result) {
                var height = bbSelf.$('.js-notification').outerHeight(true),
                    $parent = $(self).parent();
                bbSelf.$el.css({height: height});

                if ($parent.parent().hasClass('js-bb-notification')) {
                    $parent.parent().fadeOut(200,  function () {
                        $(this).remove();
                        bbSelf.$el.slideUp(250, function () {
                            $(this).show().css({height: "auto"});
                        });
                    });
                } else {
                    $parent.fadeOut(200,  function () {
                        $(this).remove();
                        bbSelf.$el.slideUp(250, function () {
                            $(this).show().css({height: "auto"});
                        });
                    });
                }
            });
        }
    });

    // ## Modals
    Ghost.Views.Modal = Ghost.View.extend({
        el: '#modal-container',
        templateName: 'modal',
        className: 'js-bb-modal',
        // Render and manages modal dismissal
        initialize: function () {
            this.render();
            var self = this;
            if (!this.model.options.confirm) {
                shortcut.add("ESC", function () {
                    self.removeElement();
                });
                $(document).on('click', '.modal-background', function (e) {
                    self.removeElement(e);
                });
            } else {
                // Initiate functions for buttons here so models don't get tied up.
                this.acceptModal = function () {
                    this.model.options.confirm.accept.func.call(this);
                    self.removeElement();
                };
                this.rejectModal = function () {
                    this.model.options.confirm.reject.func.call(this);
                    self.removeElement();
                };
                shortcut.remove("ESC");
                $(document).off('click', '.modal-background');
            }
        },
        templateData: function () {
            return this.model;
        },
        events: {
            'click .close': 'removeElement',
            'click .js-button-accept': 'acceptModal',
            'click .js-button-reject': 'rejectModal'
        },
        afterRender: function () {
            this.$(".modal-content").html(this.addSubview(new Ghost.Views.Modal.ContentView({model: this.model})).render().el);
            this.$el.children(".js-modal").center({animate: false}).css("max-height", $(window).height() - 120); // same as resize(), but the debounce causes init lag
            this.$el.addClass("active dark");

            if (document.body.style.webkitFilter !== undefined) { // Detect webkit filters
                $("body").addClass("blur");
            }
            if (_.isFunction(this.model.options.afterRender)) {
                this.model.options.afterRender.call(this);
            }
            if (this.model.options.animation) {
                this.animate(this.$el.children(".js-modal"));
            }
            var self = this;
            $(window).on('resize', self.resize);

        },
        // #### resize
        // Center and resize modal based on window height
        resize: _.debounce(function () {
            $(".js-modal").center().css("max-height", $(window).height() - 120);
        }, 50),
        // #### remove
        // Removes Backbone attachments from modals
        remove: function () {
            this.undelegateEvents();
            this.$el.empty();
            this.stopListening();
            return this;
        },
        // #### removeElement
        // Visually removes the modal from the user interface
        removeElement: function (e) {
            if (e) {
                e.preventDefault();
                e.stopPropagation();
            }

            var self = this,
                $jsModal = $('.js-modal'),
                removeModalDelay = $jsModal.transitionDuration(),
                removeBackgroundDelay = self.$el.transitionDuration();

            $jsModal.removeClass('in');

            if (!this.model.options.animation) {
                removeModalDelay = removeBackgroundDelay = 0;
            }

            setTimeout(function () {

                if (document.body.style.filter !== undefined) {
                    $("body").removeClass("blur");
                }
                self.$el.removeClass('dark');

                setTimeout(function () {
                    self.remove();
                    self.$el.removeClass('active');
                }, removeBackgroundDelay);
            }, removeModalDelay);

        },
        // #### animate
        // Animates the animation
        animate: function (target) {
            setTimeout(function () {
                target.addClass('in');
            }, target.transitionDuration());
        }
    });

    // ## Modal Content
    Ghost.Views.Modal.ContentView = Ghost.View.extend({

        template: function (data) {
            return JST['modals/' + this.model.content.template](data);
        },
        templateData: function () {
            return this.model;
        }

    });
}());
<|endoftext|>


<commit_before>var multiverse = []; // made globally visible so we can poke at it

(function() {
  'use strict';
  var index = 0; // keeps track of all universes ever made
  var fps = 30;
  var initialUniverse = 249;
  var paused = false;

  setupEvents();
  $('#current').val(initialUniverse);
  $('#current').blur();
  $('#fps').val(fps);
  updateMultiverse();

  function setupEvents() {
    $('#prev').click(function() {
      var val = Number($('#current').val());
      val--;
      if (val > 0) {
        $('#current').val(val);
        $('#current').blur();
      }
    });
    $('#next').click(function() {
      var val = Number($('#current').val());
      val++;
      $('#current').val(val);
      $('#current').blur();
    });

    $('#current').blur(function() {
      multiverse = [];
      $('.container').remove();
      makeUniverseGrid(Number($(this).val()));
    });

    $('#current').keyup(function(e) {
      if (e.which == 13) {
        $('#current').blur();
      }
    });

    $('#fps').keyup(function(e) {
      if (e.which == 13) {
        $('#fps').blur();
      }
    });

    $('#fps').blur(function() {
      fps = Number($(this).val());
    });

    $('#slower').click(function() {
      var val = Number($('#fps').val());
      var stepsize = Math.ceil(val / 3);
      if(fps > 1)
        val = val - stepsize;
      $('#fps').val(val);
      $('#fps').blur();
    });
    $('#faster').click(function() {
      var val = Number($('#fps').val());
      var stepsize = Math.ceil(val / 3);
      val = val + stepsize;
      $('#fps').val(val);
      $('#fps').blur();
    });
    $('#pause').click(function() {
      paused = !paused;
    });

    $('#randomize').click(function() {
      multiverse.forEach(function(universe) {
        universe.data.forEach(function(ele, ind, arr) {
          arr[ind] = Math.round(Math.random());
        });

      });
    });

    $('#reboot').click(function() {
      $('#current').blur();
    });
  }

  function makeUniverseGrid(size) {
    if($('#u1').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: false,
        compareRight: false
      });
    }
    if($('#u2').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: true,
        compareRight: true
      });
    }

    if($('#u3').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: true,
        compareRight: false,
        linebreak: true
      });
    }
    if($('#u4').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: false,
        compareRight: true
      });
    }
  }

  function makeUniverse(universe) {
    index++;
    universe.index = index;
    universe.run = 0;
    universe.lines = 0;
    var size = universe.size;
    var linebreak = universe.linebreak ? ' linebreak' : '';
    $('#universes').append('
<canvas id="universe' + index + '" width="' + size + '" height="' + size + '"></canvas>

');
    universe.data = [];
    multiverse.push(universe);
  }

  function updateMultiverse() {
    setTimeout(function() {
      requestAnimationFrame(updateMultiverse);
    }, 1000 / fps);

    if (paused)
      return;

    multiverse.forEach(function(universe, index) {

      var ctx = $('#universe' + universe.index)[0].getContext('2d');
      ctx.clearRect(0, 0, universe.size, universe.size);
      var y = 0;

      for (var i = 0; i < universe.size; i++) {
        var j = universe.moveLeft ? universe.size : 0;
        var breakCondition = universe.moveLeft ? -1 : universe.size;
        while (1) {
          var val;
          var leftNeighbor, rightNeighbor, chosenNeighbor;
          leftNeighbor = j === 0 ? universe.size - 1 : j - 1;
          rightNeighbor = j === universe.size - 1 ? 0 : j + 1;
          chosenNeighbor = universe.compareRight ? rightNeighbor : leftNeighbor;

          if (universe.data[j] === undefined)
            val = 1;
          else
            val = universe.data[j] ^ universe.data[chosenNeighbor];

          universe.data[j] = val;

          if (universe.data[j])
            ctx.fillRect(j, y, 1, 1);

          j = universe.moveLeft ? j - 1 : j + 1;
          if (j === breakCondition)
            break;
        }

        y++;
      }
    });
  }

}());
<commit_msg>remove unused variables<commit_after>var multiverse = []; // made globally visible so we can poke at it

(function() {
  'use strict';
  var index = 0; // keeps track of all universes ever made
  var fps = 30;
  var initialUniverse = 249;
  var paused = false;

  setupEvents();
  $('#current').val(initialUniverse);
  $('#current').blur();
  $('#fps').val(fps);
  updateMultiverse();

  function setupEvents() {
    $('#prev').click(function() {
      var val = Number($('#current').val());
      val--;
      if (val > 0) {
        $('#current').val(val);
        $('#current').blur();
      }
    });
    $('#next').click(function() {
      var val = Number($('#current').val());
      val++;
      $('#current').val(val);
      $('#current').blur();
    });

    $('#current').blur(function() {
      multiverse = [];
      $('.container').remove();
      makeUniverseGrid(Number($(this).val()));
    });

    $('#current').keyup(function(e) {
      if (e.which == 13) {
        $('#current').blur();
      }
    });

    $('#fps').keyup(function(e) {
      if (e.which == 13) {
        $('#fps').blur();
      }
    });

    $('#fps').blur(function() {
      fps = Number($(this).val());
    });

    $('#slower').click(function() {
      var val = Number($('#fps').val());
      var stepsize = Math.ceil(val / 3);
      if(fps > 1)
        val = val - stepsize;
      $('#fps').val(val);
      $('#fps').blur();
    });
    $('#faster').click(function() {
      var val = Number($('#fps').val());
      var stepsize = Math.ceil(val / 3);
      val = val + stepsize;
      $('#fps').val(val);
      $('#fps').blur();
    });
    $('#pause').click(function() {
      paused = !paused;
    });

    $('#randomize').click(function() {
      multiverse.forEach(function(universe) {
        universe.data.forEach(function(ele, ind, arr) {
          arr[ind] = Math.round(Math.random());
        });

      });
    });

    $('#reboot').click(function() {
      $('#current').blur();
    });
  }

  function makeUniverseGrid(size) {
    if($('#u1').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: false,
        compareRight: false
      });
    }
    if($('#u2').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: true,
        compareRight: true
      });
    }

    if($('#u3').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: true,
        compareRight: false,
        linebreak: true
      });
    }
    if($('#u4').is(':checked')) {
      makeUniverse({
        size: size,
        moveLeft: false,
        compareRight: true
      });
    }
  }

  function makeUniverse(universe) {
    index++;
    universe.index = index;
    var size = universe.size;
    var linebreak = universe.linebreak ? ' linebreak' : '';
    $('#universes').append('
<canvas id="universe' + index + '" width="' + size + '" height="' + size + '"></canvas>

');
    universe.data = [];
    multiverse.push(universe);
  }

  function updateMultiverse() {
    setTimeout(function() {
      requestAnimationFrame(updateMultiverse);
    }, 1000 / fps);

    if (paused)
      return;

    multiverse.forEach(function(universe, index) {

      var ctx = $('#universe' + universe.index)[0].getContext('2d');
      ctx.clearRect(0, 0, universe.size, universe.size);
      var y = 0;

      for (var i = 0; i < universe.size; i++) {
        var j = universe.moveLeft ? universe.size : 0;
        var breakCondition = universe.moveLeft ? -1 : universe.size;
        while (1) {
          var val;
          var leftNeighbor, rightNeighbor, chosenNeighbor;
          leftNeighbor = j === 0 ? universe.size - 1 : j - 1;
          rightNeighbor = j === universe.size - 1 ? 0 : j + 1;
          chosenNeighbor = universe.compareRight ? rightNeighbor : leftNeighbor;

          if (universe.data[j] === undefined)
            val = 1;
          else
            val = universe.data[j] ^ universe.data[chosenNeighbor];

          universe.data[j] = val;

          if (universe.data[j])
            ctx.fillRect(j, y, 1, 1);

          j = universe.moveLeft ? j - 1 : j + 1;
          if (j === breakCondition)
            break;
        }

        y++;
      }
    });
  }

}());
<|endoftext|>


<commit_before>import mem from 'mem';

import { Permissions, Roles, Users, Subscriptions } from '../../../models/server/raw';

const getRole = mem((role) => Roles.findOne({ _id: role }));

const rolesHasPermission = mem(async (permission, roles) => {
	const result = await Permissions.findOne({ _id: permission, roles: { $in: roles } });
	return !!result;
});

const subscriptionHasPermission = mem(async (uid, permission, roles, rid) => {
	if (rid == null) {
		return;
	}

	const query = {
		'u._id': uid,
		rid,
		roles: { $in: roles },
	};

	return !!await Subscriptions.findOne(query, { fields: { roles: 1 } });
}, { maxAge: 5000 });

export const clearCache = () => {
	mem.clear(getRole);
	mem.clear(rolesHasPermission);
	mem.clear(subscriptionHasPermission);
};

const groupRolesByScope = async (sortedUserRoles) => (await Promise.all(sortedUserRoles.map(getRole))).reduce((roles, role) => {
	roles[role.scope || 'Users'] = roles[role.scope || 'Users'] ? roles[role.scope || 'Users'].concat([role._id]) : [].concat([role._id]);
	return roles;
}, {});

async function atLeastOne(uid, permissions = [], scope) {
	const { roles: userRoles } = await Users.findOne({ _id: uid });

	const sortedUserRoles = userRoles.sort((a, b) => a.localeCompare(b));

	const roles = await groupRolesByScope(sortedUserRoles);
	const keys = Object.keys(roles);
	for (let index = 0; index < keys.length; index++) {
		const key = keys[index];
		switch (key) {
			case 'Users':
				for (const permission of permissions) {
					if (await rolesHasPermission(permission, roles[key])) { // eslint-disable-line
						return true;
					}
				}
				break;
			case 'Subscriptions':
				const found = await subscriptionHasPermission(uid, roles[key], scope);// eslint-disable-line
				if (found) {
					return true;
				}
				break;
		}
	}

	return false;
}

async function all(uid, permissions = [], scope) {
	const { roles: userRoles } = await Users.findOne({ _id: uid });

	const sortedUserRoles = userRoles.sort((a, b) => a.localeCompare(b));

	const roles = await groupRolesByScope(sortedUserRoles);

	const keys = Object.keys(roles);

	for (let index = 0; index < keys.length; index++) {
		const key = keys[index];
		switch (key) {
			case 'Users':
				for (const permission of permissions) {
					if (!await rolesHasPermission(permission, roles[key])) { // eslint-disable-line
						return false;
					}
				}
				break;
			default:
			case 'Subscriptions':
				const found = await subscriptionHasPermission(uid, roles[key], scope);// eslint-disable-line
				if (!found) {
					return false;
				}
				break;
		}
	}

	return true;
}

function _hasPermission(userId, permissions, scope, strategy) {
	if (!userId) {
		return false;
	}
	return strategy(userId, [].concat(permissions), scope);
}

export const hasAllPermissionAsync = async (userId, permissions, scope) => _hasPermission(userId, permissions, scope, all);
export const hasPermissionAsync = async (userId, permissionId, scope) => _hasPermission(userId, permissionId, scope, all);
export const hasAtLeastOnePermissionAsync = async (userId, permissions, scope) => _hasPermission(userId, permissions, scope, atLeastOne);

export const hasAllPermission = (userId, permissions, scope) => Promise.await(hasAllPermissionAsync(userId, permissions, scope));
export const hasPermission = (userId, permissionId, scope) => Promise.await(hasPermissionAsync(userId, permissionId, scope));
export const hasAtLeastOnePermission = (userId, permissions, scope) => Promise.await(hasAtLeastOnePermissionAsync(userId, permissions, scope));
<commit_msg>Regression: fix unknown role breaking hasPermission (#15641)<commit_after>import mem from 'mem';

import { Permissions, Roles, Users, Subscriptions } from '../../../models/server/raw';

const getRole = mem((role) => Roles.findOne({ _id: role }));

const rolesHasPermission = mem(async (permission, roles) => {
	const result = await Permissions.findOne({ _id: permission, roles: { $in: roles } });
	return !!result;
});

const exists = (item) => !!item;

const subscriptionHasPermission = mem(async (uid, permission, roles, rid) => {
	if (rid == null) {
		return;
	}

	const query = {
		'u._id': uid,
		rid,
		roles: { $in: roles },
	};

	return !!await Subscriptions.findOne(query, { fields: { roles: 1 } });
}, { maxAge: 5000 });

export const clearCache = () => {
	mem.clear(getRole);
	mem.clear(rolesHasPermission);
	mem.clear(subscriptionHasPermission);
};

const groupRolesByScope = async (sortedUserRoles) => (await Promise.all(sortedUserRoles.map(getRole))).filter(exists).reduce((roles, role) => {
	roles[role.scope || 'Users'] = roles[role.scope || 'Users'] ? roles[role.scope || 'Users'].concat([role._id]) : [].concat([role._id]);
	return roles;
}, {});

async function atLeastOne(uid, permissions = [], scope) {
	const { roles: userRoles } = await Users.findOne({ _id: uid });

	const sortedUserRoles = userRoles.sort((a, b) => a.localeCompare(b));

	const roles = await groupRolesByScope(sortedUserRoles);
	const keys = Object.keys(roles);
	for (let index = 0; index < keys.length; index++) {
		const key = keys[index];
		switch (key) {
			case 'Users':
				for (const permission of permissions) {
					if (await rolesHasPermission(permission, roles[key])) { // eslint-disable-line
						return true;
					}
				}
				break;
			case 'Subscriptions':
				const found = await subscriptionHasPermission(uid, roles[key], scope);// eslint-disable-line
				if (found) {
					return true;
				}
				break;
		}
	}

	return false;
}

async function all(uid, permissions = [], scope) {
	const { roles: userRoles } = await Users.findOne({ _id: uid });

	const sortedUserRoles = userRoles.sort((a, b) => a.localeCompare(b));

	const roles = await groupRolesByScope(sortedUserRoles);

	const keys = Object.keys(roles);

	for (let index = 0; index < keys.length; index++) {
		const key = keys[index];
		switch (key) {
			case 'Users':
				for (const permission of permissions) {
					if (!await rolesHasPermission(permission, roles[key])) { // eslint-disable-line
						return false;
					}
				}
				break;
			default:
			case 'Subscriptions':
				const found = await subscriptionHasPermission(uid, roles[key], scope);// eslint-disable-line
				if (!found) {
					return false;
				}
				break;
		}
	}

	return true;
}

function _hasPermission(userId, permissions, scope, strategy) {
	if (!userId) {
		return false;
	}
	return strategy(userId, [].concat(permissions), scope);
}

export const hasAllPermissionAsync = async (userId, permissions, scope) => _hasPermission(userId, permissions, scope, all);
export const hasPermissionAsync = async (userId, permissionId, scope) => _hasPermission(userId, permissionId, scope, all);
export const hasAtLeastOnePermissionAsync = async (userId, permissions, scope) => _hasPermission(userId, permissions, scope, atLeastOne);

export const hasAllPermission = (userId, permissions, scope) => Promise.await(hasAllPermissionAsync(userId, permissions, scope));
export const hasPermission = (userId, permissionId, scope) => Promise.await(hasPermissionAsync(userId, permissionId, scope));
export const hasAtLeastOnePermission = (userId, permissions, scope) => Promise.await(hasAtLeastOnePermissionAsync(userId, permissions, scope));
<|endoftext|>