<commit_before>var Scatter = function(settings) {
	this.settings = settings
	this.data = this.settings.data
	this.defineFunctions()
	this.setScales()

	this.div = d3.select('#' + settings.container).append('div').attr('id', settings.id).attr('class', 'chart')
		.style('position', 'absolute')
		.style('top', this.settings.position.top + 'px')
		.style('left', this.settings.position.left + 'px')
		.style("width", this.settings.width  + 'px')
		.style("height", this.settings.height + 'px')

	this.title = this.div.append('div').attr('id', settings.id + '-title').style('width', this.settings.width + 'px').style('text-align', 'center').text('Topic ' + this.settings.topic + ' Proportions')
	this.build()
}

Scatter.prototype.defineFunctions = function() {
	var that = this

	that.legendRectFunc = function(leg) {
		leg.attr("width", that.settings.legend.rectWidth)
		   .attr("height", function(d) {
				return that.settings.legend.rectHeight
			})
			.attr('fill', function(d) {
				return that.colorScale(d)
			})
			.attr('class', function(d) {
				return 'leg-rect'
			})
	}

	that.legendTextFunc = function(txt) {
		txt.text(function(d) {
			var limit = Math.floor((that.settings.margin.right -10)/10.5)
			var fullText =   d
			var text = fullText
// 			var text = fullText.length > limit ?  fullText.substring(0,limit) + '...' : fullText
			return text
		})
		.attr('fulltext', function(d) {
			var fulltext =   d
			return fulltext
		})
		.attr('x', that.settings.legend.rectWidth + 5)
		.attr('y', that.settings.legend.rectHeight/2)
		.attr('fill', function(d) {
			var color =  'black'
			return color
		})
		.attr('class', function(d) {
			return 'leg-text'
		})
	}
	that.zoom = function() {
 		that.points.attr('transform', that.transform)
		that.xaxisLabels.call(that.xaxis)
		that.yaxisLabels.call(that.yaxis)
	}

	that.transform = function(d) {
	  return "translate(" + that.xScale(d.x) + "," + that.yScale(d.y) + ")";
	}

	that.pointFunction = function(point) {
		point
		.attr('transform', that.transform)
		.attr('r', function(d) {
			var radius =  d.id == that.settings.highlighted ? that.settings.highlightedRadius : that.settings.radius
			return radius
		})
		.attr('class', function(d) {
			var klass = d.id == that.settings.highlighted ? 'point highlighted' : 'point'
			return klass
		})
		.attr('fill', function(d) {
			return that.colorScale(d.colorValue)
		})
		.attr('id', function(d) {return 'id_' + d.id})
	}
}

Scatter.prototype.setScales = function() {
	var that = this
	this.settings.legend.rectHeight = this.settings.height/(2*this.settings.colorLabels.length) >30 ? 30 : this.settings.height/(2*this.settings.colorLabels.length)
	this.settings.radiusHighlighted = this.settings.radius * 3
	this.xScale = d3.scale.linear().domain(that.settings.domain.x).range([this.settings.highlightedRadius + this.settings.stroke, this.settings.width - this.settings.highlightedRadius -  this.settings.stroke - this.settings.margin.left - this.settings.margin.right])
	this.yScale = d3.scale.linear().domain(that.settings.domain.y).range([this.settings.highlightedRadius+ this.settings.stroke, this.settings.height - this.settings.highlightedRadius -  this.settings.stroke - this.settings.margin.top - this.settings.margin.bottom ])
	this.colorScale = this.settings.colorVariableType == "string" ? d3.scale.category10() : d3.scale.linear().domain(d3.range(this.settings.domain.colors[1],this.settings.domain.colors[0], -(this.settings.domain.colors[1] - this.settings.domain.colors[0])/11)).range(colorbrewer['RdYlBu'][11])
	this.legendScale = d3.scale.linear()
		.domain(this.settings.domain.x)
		.range([0,this.settings.legend.width]);

	this.xaxis = d3.svg.axis()
		.scale(that.xScale)
		.tickValues(that.settings.xVariableType == "string" ? that.settings.xLabels.map(function(d,i) {return i}) : null)
		.tickFormat(function(d) {
			return that.settings.xVariableType == "string" ? that.settings.xLabels[d] : d
		})
		.orient("bottom")

	this.yaxis = d3.svg.axis()
		.scale(that.yScale)
		.orient('left')
}

Scatter.prototype.build = function() {
	var that = this
	this.wrapper = this.div.append("div")
		.attr('id', this.settings.id + '-svg-wrapper')
		.style('height', that.settings.height + 'px')

	this.xAxisSvg = this.wrapper.append('svg').attr('id', 'xaxis')
		.style('position', 'absolute')
		.style('top', (this.yScale.range()[1] + 25) + 'px')
		.style('left', this.settings.margin.left)
		.style('width', that.settings.width + 'px')
		.style('height', 80+ 'px')

	this.yAxisSvg = this.wrapper.append('svg').attr('id', 'yaxis').style('height', that.yScale.range()[1] + + that.settings.highlightedRadius + that.settings.stroke +'px')

	this.pointsSvg = this.wrapper.append('svg')
		.attr("width", this.xScale.range()[1] + that.settings.highlightedRadius + that.settings.stroke)
		.attr("height", this.yScale.range()[1] + that.settings.highlightedRadius+ that.settings.stroke )
		.attr('id', this.settings.id + '-svg')
		.style('position', 'absolute')
		.style('left', this.settings.margin.left + 'px')
		.attr("transform", "translate(" + this.settings.margin.left + "," +10+ ")")

	this.zoomG = this.pointsSvg.append("g")
    	.call(d3.behavior.zoom().x(that.xScale).y(that.yScale).scaleExtent([1, 8]).on("zoom", that.zoom));

	this.zoomRect = this.zoomG.append("rect")
		.attr("class", "overlay")
		.attr("width", this.xScale.range()[1])
		.attr("height", this.yScale.range()[1])

	this.g = this.pointsSvg.append("g")
		.attr('id', this.settings.id + '-g')

	this.points = this.g.selectAll('.point')
				.data(this.data, function(d) {return d.id})
				.enter().append('circle')
				.call(this.pointFunction)

	this.xaxisLabels = this.xAxisSvg.append("g")
					.attr("class", "axis xaxis")
					.attr("id", "xaxis-label")
					.call(this.xaxis)

	this.xtitle = this.xAxisSvg.append('text')
					.text(this.settings.xtitle)
					.attr('transform', 'translate(' + ((this.xScale.range()[1])/2) + ',' + (40)+ ')')
					.attr('id', 'xaxistext')

	this.yaxisLabels = this.yAxisSvg.append('g')
						.attr('class', 'axis yaxis')
						.attr('id', 'yaxis-label')
						.attr('transform', 'translate(' + this.settings.margin.left + ',0)')
						.call(this.yaxis)

	this.ytitle = this.yAxisSvg.append('text')
					.text(this.settings.ytitle)
					.attr('transform', 'translate(' + (30) + ',' + (this.settings.height/5*3)+ ') rotate(-90)')
					.attr('id', 'yaxistext')

	this.moveHighlighted()
	if(this.settings.colorVariableType == 'integer') this.buildContinuousLegend()
	else this.buildCategoricalLegend()
	this.addHover()
}

Scatter.prototype.buildContinuousLegend = function() {
	var that = this
	that.legendWrapper = that.div.append('div').attr('id', that.settings.id + '-legend-wrapper').style('pointer-events', 'none')
	that.legendDiv = that.legendWrapper.append('div').attr('id', that.settings.id + '-legend-div').style('position', 'absolute').style('top', (this.settings.height - this.settings.margin.bottom) + 'px')
	that.legend = that.legendDiv
		.append("svg")
		.attr('id', that.settings.id + '-legend-svg')
		.attr("height", that.settings.legend.height + 40)
		.attr("width", that.settings.legend.width + that.settings.legend.shift + 14)

	that.gradient = that.legend
		.append("svg:defs")
			.append("svg:linearGradient")
			.attr("id", "map-gradient")
			.attr("x1", "0%")
			.attr("y1", "0%")
			.attr("x2", "100%")
			.attr("y2", "0%");

	$.extend([],that.settings.colorRange).reverse().forEach(function(d,i){
			that.gradient.append("svg:stop")
				.attr("offset",((i+1)/(12)))
				.attr("stop-color", d)
				.attr('id', 'stop-color-' + i)
		});

	that.legendBar = that.legend.append("g")
			.attr('transform', 'translate(' + that.settings.legend.shift+',0)')
			.append('rect').attr('id', that.settings.id + '-legendrect')
			.attr('y', '0px')
			.attr('x', '0px')
			.attr('height', that.settings.legend.height)
			.attr('width',  that.settings.legend.width)
			.attr('stroke', 'none')
			.attr('fill', 'url(#map-gradient)')

	that.legendAxes = d3.svg.axis()
		.scale(that.legendScale)
		.orient('bottom')

	that.legendLabels = that.legend.append('g')
		.attr('transform', 'translate(' + that.settings.legend.shift+ ',' + (that.settings.legend.height) + ')')
		.attr('class', 'axis')
		.call(that.legendAxes);

	that.legendText = that.legend.append('g')
		.attr('transform', 'translate(' + (that.settings.legend.shift -40)+ ',' + (that.settings.legend.height/2) + ')')
		.append('text').text(this.settings.legendTitle)

}

Scatter.prototype.moveHighlighted = function() {
	var select = $("#id_" + this.settings.highlighted)[0]
	select.parentNode.appendChild(select)
}

Scatter.prototype.updateHighlighted = function(hl) {
	this.settings.highlighted = hl
	d3.selectAll('.highlighted').attr('class', 'point').attr('r', this.settings.radius)
	d3.select('#id_'  + hl).attr('class', 'point highlighted').attr('r', this.settings.highlightedRadius)
	this.moveHighlighted()

}

Scatter.prototype.updatePosition = function(settings) {
	var that = this
	this.settings = settings
	this.title.style('width', this.settings.width + 'px')
	d3.select('#' + settings.id + '-title').text('Topic ' + this.settings.topic + ' Proportions')
	this.data = settings.data
	this.setScales()
	this.xtitle.attr('transform', 'translate(' + ((this.xScale.range()[1])/2) + ',' + (40)+ ')').text(this.settings.xtitle)
	this.ytitle.attr('transform', 'translate(' + (30) + ',' + (this.settings.height/5*3)+ ') rotate(-90)')
	this.zoomRect.attr("width", this.xScale.range()[1])
		.attr("height", this.yScale.range()[1])

	this.pointsSvg
		.attr("width", this.xScale.range()[1] + that.settings.highlightedRadius + that.settings.stroke)
		.attr("height", this.yScale.range()[1] + that.settings.highlightedRadius+ that.settings.stroke )

	this.xAxisSvg.transition().duration(500).style('top', (this.yScale.range()[1] + 25) + 'px')
		.style('left', this.settings.margin.left)
		.style('width', that.settings.width + 'px')

	this.yAxisSvg.style('height', that.yScale.range()[1] + + that.settings.highlightedRadius + that.settings.stroke +'px')
	this.xaxisLabels.transition().duration(500).call(this.xaxis)
	this.yaxisLabels.transition().duration(500).call(this.yaxis)
 	this.pointsSvg.selectAll('.point').data(this.data, function(d) {return (d.id)}).transition().duration(500).call(this.pointFunction)

	setTimeout(function() {
		that.zoomG.call(d3.behavior.zoom().x(that.xScale).y(that.yScale).scaleExtent([1, 8]).on("zoom", that.zoom));
	}, 700)
	$('#' + this.settings.id + '-legend-wrapper').remove()
	if(this.settings.colorVariableType == 'integer') this.buildContinuousLegend()
	else this.buildCategoricalLegend()
}

Scatter.prototype.buildCategoricalLegend = function(parent, id) {
	var that = this
	var x =  that.xScale.range()[1]
	var y = 10
	legendData = that.settings.colorLabels
	if(legendData.length == 1) return
	var labelScale = d3.scale.linear().domain([legendData.length-1,0]).range([0,(that.settings.height - 50)])
	var legendSvg = this.wrapper.append('svg').attr('id', this.settings.id + '-legend-wrapper').style('position', 'absolute').style("left", that.settings.margin.left + 'px').style('pointer-events', 'none')

	var legend = legendSvg.append('g').attr('transform', 'translate(' + (x) + ',' +(y) + ')')
	var labels = legend.selectAll('g')
					.data(legendData, function(d) {return d})
					.enter().append('g')
					.attr('class', 'legend-g')
					.attr('transform', function(d,i) {return 'translate(0,' +((i*40) ) + ')' })

	var legRects = labels.append('rect').call(that.legendRectFunc)

	var text = labels.append('text').call(that.legendTextFunc)

}

Scatter.prototype.setOpacity  = function(opacity) {
	this.g.selectAll('.point').style('opacity', opacity)
}

Scatter.prototype.setRadius  = function(radius) {
	this.g.selectAll('.point').transition().duration(500).attr('r', radius)
}

Scatter.prototype.addHover = function() {
	var that = this
	$('.point').poshytip({
		slide: false,
		followCursor: true,
		alignTo: 'cursor',
		showTimeout: 0,
		liveevents:true,
		hideTimeout: 0,
		alignX: 'center',
		alignY: 'inner-bottom',
		className: 'tip',
		offsetY: 10,
		content: function(a,tip){
			var d = this.__data__
			var formatter = d3.format('.2s')
			var text = 'ID: ' + d.id + '
'
			text += '' + that.settings.ytitle + ':  ' + formatter(d.y) + '
'
			text += '' + that.settings.xtitle + ':  ' + that.settings.xLabels[d.x]
			return text
		}
	})

}<commit_msg>Removed server_src/static/ScatterPlot1/js/scatter.js<commit_after><|endoftext|>


<commit_before>import Reflux from 'reflux';
import $ from 'jQuery';
import projectsData from './projectsData';

let ProjectsActions = Reflux.createActions([
  'loadProjects',
  'loadProjectsSuccess',
  'loadProjectsError'
]);

ProjectsActions.loadProjects.preEmit = function(data){
  let endpoint = "http://localhost:1337/js/app/mock.json";
  let promise = $.ajax({ url: endpoint, type: 'GET', dataType: 'json' });

  promise.success( (resp) => {
    projectsData.manageResponse(resp, function(data){
      ProjectsActions.loadProjectsSuccess(data);
    })
  })

  promise.error( ()=> {
    ProjectsActions.loadProjectsError('an error occured');
  })

};

export default ProjectsActions;<commit_msg>make mock data path relative<commit_after>import Reflux from 'reflux';
import $ from 'jQuery';
import projectsData from './projectsData';

let ProjectsActions = Reflux.createActions([
  'loadProjects',
  'loadProjectsSuccess',
  'loadProjectsError'
]);

ProjectsActions.loadProjects.preEmit = function(data){
  let endpoint = "/js/app/mock.json";
  let promise = $.ajax({ url: endpoint, type: 'GET', dataType: 'json' });

  promise.success( (resp) => {
    projectsData.manageResponse(resp, function(data){
      ProjectsActions.loadProjectsSuccess(data);
    })
  })

  promise.error( ()=> {
    ProjectsActions.loadProjectsError('an error occured');
  })

};

export default ProjectsActions;<|endoftext|>


<commit_before>import React from 'react'
import Link from 'gatsby-link'
import styled from 'styled-components'

import '../styles/global.css.js'
import {linkTextColor} from '../styles/variables.css.js'

const MainSection = styled.section`
  height: 100%;
  display: flex;
`

const MainSectionContent = styled.section`
  padding: 2rem 0;
  margin: auto;
  height: auto;
  width: 70%;
  max-width: 750px;
  & * {
    margin-bottom: 1rem;
  }
`

const Title = styled.h1`
  text-align: center;
  font-size: 3rem;
`

const Subtitle = styled.h2`
  text-align: center;
  font-size: 2rem;
`

const Text = styled.p`
  text-align: center;
  font-size: 1.1rem;
  line-height: 1.5rem;
`

const InlineLink = styled.a`
  color: ${linkTextColor};
  text-decoration: none;
  &:hover {
    text-decoration: underline;
  }
`

export default () => (
  <MainSection>
    <MainSectionContent>
      <Title>Ander Suárez Martínez</Title>
      <Subtitle>Frontend developer at <InlineLink href="http://www.unbound.com">Unbound</InlineLink>. I build websites.</Subtitle>
      <Text>Previously, frontend lead at <InlineLink href="http://www.jinnapp.com">Jinn</InlineLink>. I co-founded <InlineLink href="http://perpetuall.net/">Perpetuall</InlineLink>. I was born in Bilbao, and moved to the UK looking for new challenges. I like music & arts. I am a guitarist in a band called <InlineLink href="http://walnut.bandcamp.com">Walnut</InlineLink>.</Text>
      <Text>Find me at <InlineLink href="mailto:me@andersuarez.com">me@andersuarez.com</InlineLink></Text>
    </MainSectionContent>
  </MainSection>
)
<commit_msg>Update<commit_after>import React from 'react'
import Link from 'gatsby-link'
import styled from 'styled-components'

import '../styles/global.css.js'
import { linkTextColor } from '../styles/variables.css.js'

const MainSection = styled.section`
  height: 100%;
  display: flex;
`

const MainSectionContent = styled.section`
  padding: 2rem 0;
  margin: auto;
  height: auto;
  width: 70%;
  max-width: 750px;
  & * {
    margin-bottom: 1rem;
  }
`

const Title = styled.h1`
  text-align: center;
  font-size: 3rem;
`

const Subtitle = styled.h2`
  text-align: center;
  font-size: 2rem;
`

const Text = styled.p`
  text-align: center;
  font-size: 1.1rem;
  line-height: 1.5rem;
`

const InlineLink = styled.a`
  color: ${linkTextColor};
  text-decoration: none;
  &:hover {
    text-decoration: underline;
  }
`

export default () => (
  <MainSection>
    <MainSectionContent>
      <Title>Ander Suárez Martínez</Title>
      <Subtitle>Senior Frontend Developer at <InlineLink href="http://www.unbound.com">Unbound</InlineLink>. I build websites.</Subtitle>
      <Text>Previously, frontend lead at <InlineLink href="http://www.jinnapp.com">Jinn</InlineLink>. I co-founded <InlineLink href="http://perpetuall.net/">Perpetuall</InlineLink>. I was born in Bilbao, and moved to the UK looking for new challenges. I like music & arts. I play guitar for <InlineLink href="http://walnut.bandcamp.com">Walnut</InlineLink>.</Text>
      <Text>Find me at <InlineLink href="mailto:me@andersuarez.com">me@andersuarez.com</InlineLink></Text>
    </MainSectionContent>
  </MainSection>
)
<|endoftext|>


<commit_before>import React from "react";

import backtoback from "../assets/backtoback.png";
import css from "../assets/css3.png";
import react from "../assets/reactNE.png";
import html from "../assets/HTML5_Badge_512.png";
import logo from "../assets/logo-title-light.png";
import todd from "../assets/todd_smart.png";

import backtoback from "../../assets/backtoback.png";
import css from "../../assets/css3.png";
import react from "../../assets/reactNE.png";
import html from "../../assets/HTML5_Badge_512.png";
import logo from "../../assets/logo-title-light.png";
import todd from "../../assets/todd_smart.jpg";

import "../layouts/main.css";
import "../layouts/fonts/font-awesome-4.7.0/css/font-awesome.min.css";

export default () =>

What is Smart Binary?

            Smart Binary, LLC is an{" "}

              incorporated
            {" "}
            software consultancy.

            We are a partnership. Each technical partner is foremost a
            consultant for our clients. They each have proven, referenceable
            track records of analyzing, designing, implementing, and maintaining
            solutions ranging from stealth startup quick releases to long-term
            enterprise solutions for the world's largest companies.

            If and when you have a need to build out a team to meet your most
            extreme timelines, our partners are able to tap into our closest,
            most trusted, and proven colleagues to scale and delivery
            accordingly. We will always provide you with the opportunity to meet
            and even interview colleagues that we recommend to you to help scale
            up and deliver.

            To determine our corp-to-corp, all-inclusive rate, we evaluate the
            following aspects of the engagement:

client location

on-site / remote percentage

project type

technology stack

requested role(s)

requested responsibilities

length of engagement

problem domain

What do we do?

            Smart Binary is an Software Consultancy specializing in{" "}
            Mobile Application Development. We are capable of handling
            the full stack from UI to API to DB to Cloud. Founded in 1999, Smart
            Binary excels in customized, one-on-one client interaction in
            applications consulting services. We strive to provide the highest
            levels of communication and produce high quality results to
            businesses across the USA and beyond, at an affordable rate.

            Our Partners combine for more than 40-years of academic and
            professional experience. With our skill sets, experience levels, and
            industry connections, Smart Binary allows you to bypass expensive
            agencies and go

              "Direct to the Source".

              "Direct to the Source"

            Our Partners are industry experts that you will have direct access
            to.

What does that fiscally mean to you?

            ...no need to pay heavy fees to post job ads...

            ...no need to pay a 50% up-charge to recruiters...

            ...no need to spend weeks interviewing candidates...

              Save time and money by going Direct to the Source.

            We look forward to partnering with you for your development and
            design needs.

Meet the Technical Partners

            Todd Smart

            Brad Bohen

Todd Smart

Software Engineer | Mentor | Agile Coach

            Todd is a professional software engineer with nearly three decades
            of full-stack development experience.

            Todd builds enterprise-level mobile and web applications using React
            Native, React, GraphQL, and Node.

            Academically, Todd attained a master’s degree in Computer Science.

Interested in getting in touch?

      <form className="row container p-0 m-0">

            <input
              type="text"
              className="form-control"
              id="contactName"
              placeholder="Your Name"
            />

            <input
              type="email"
              className="form-control"
              id="emailAddress"
              placeholder="Enter email"
            />

            <input
              type="email"
              className="form-control"
              id="subject"
              placeholder="Subject"
            />

            <textarea
              className="form-control"
              id="message"
              rows="3"
              placeholder="Your Message"
            />

          <button type="submit" className="btn btn-block btn-primary">
            Send
          </button>

      </form>

;
<commit_msg>WEB-9 fix build (#6)<commit_after>import React from "react";

import backtoback from "../../assets/backtoback.png";
import css from "../../assets/css3.png";
import react from "../../assets/reactNE.png";
import html from "../../assets/HTML5_Badge_512.png";
import logo from "../../assets/logo-title-light.png";
import todd from "../../assets/todd_smart.jpg";

import "../layouts/main.css";
import "../layouts/fonts/font-awesome-4.7.0/css/font-awesome.min.css";

export default () =>

What is Smart Binary?

            Smart Binary, LLC is an{" "}

              incorporated
            {" "}
            software consultancy.

            We are a partnership. Each technical partner is foremost a
            consultant for our clients. They each have proven, referenceable
            track records of analyzing, designing, implementing, and maintaining
            solutions ranging from stealth startup quick releases to long-term
            enterprise solutions for the world's largest companies.

            If and when you have a need to build out a team to meet your most
            extreme timelines, our partners are able to tap into our closest,
            most trusted, and proven colleagues to scale and delivery
            accordingly. We will always provide you with the opportunity to meet
            and even interview colleagues that we recommend to you to help scale
            up and deliver.

            To determine our corp-to-corp, all-inclusive rate, we evaluate the
            following aspects of the engagement:

client location

on-site / remote percentage

project type

technology stack

requested role(s)

requested responsibilities

length of engagement

problem domain

What do we do?

            Smart Binary is an Software Consultancy specializing in{" "}
            Mobile Application Development. We are capable of handling
            the full stack from UI to API to DB to Cloud. Founded in 1999, Smart
            Binary excels in customized, one-on-one client interaction in
            applications consulting services. We strive to provide the highest
            levels of communication and produce high quality results to
            businesses across the USA and beyond, at an affordable rate.

            Our Partners combine for more than 40-years of academic and
            professional experience. With our skill sets, experience levels, and
            industry connections, Smart Binary allows you to bypass expensive
            agencies and go

              "Direct to the Source".

              "Direct to the Source"

            Our Partners are industry experts that you will have direct access
            to.

What does that fiscally mean to you?

            ...no need to pay heavy fees to post job ads...

            ...no need to pay a 50% up-charge to recruiters...

            ...no need to spend weeks interviewing candidates...

              Save time and money by going Direct to the Source.

            We look forward to partnering with you for your development and
            design needs.

Meet the Technical Partners

            Todd Smart

            Brad Bohen

Todd Smart

Software Engineer | Mentor | Agile Coach

            Todd is a professional software engineer with nearly three decades
            of full-stack development experience.

            Todd builds enterprise-level mobile and web applications using React
            Native, React, GraphQL, and Node.

            Academically, Todd attained a master’s degree in Computer Science.

Interested in getting in touch?

      <form className="row container p-0 m-0">

            <input
              type="text"
              className="form-control"
              id="contactName"
              placeholder="Your Name"
            />

            <input
              type="email"
              className="form-control"
              id="emailAddress"
              placeholder="Enter email"
            />

            <input
              type="email"
              className="form-control"
              id="subject"
              placeholder="Subject"
            />

            <textarea
              className="form-control"
              id="message"
              rows="3"
              placeholder="Your Message"
            />

          <button type="submit" className="btn btn-block btn-primary">
            Send
          </button>

      </form>

;
<|endoftext|>


<commit_before>export { ChannelPartInfo };
export { FiltersBiasesPartInfo };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";

/**
 * Half channels information. Describe channel index range of lower half or higher half.
 *
 * @member {number} inChannelBegin
 *   The beginning input channel index of this part.
 *
 * @member {number} inChannelEnd
 *   The ending input channel index of this part.
 *
 * @member {number} outputChannelCount
 *   The channel count of output.
 *
 * @member {boolean} bPassThrough
 *   If true, this is a pass-through part and it will pass-through input channel index in [ inChannelBegin, inChannelEnd ) to output.
 * Otherwise, this is a non-pass-through part and it will using filters and biases extracted from weights array to convolve input channel
 * index in [ inChannelBegin, inChannelEnd ) to output.
 */
class ChannelPartInfo extends Recyclable.Root {

  /**
   * Used as default Pointwise.ChannelPartInfo provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "Pointwise.ChannelPartInfo.Pool", ChannelPartInfo, ChannelPartInfo.setAsConstructor );

  /**
   */
  constructor( inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough ) {
    super();
    ChannelPartInfo.setAsConstructor_self.call( this, inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough );
  }

  /** @override */
  static setAsConstructor( inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough ) {
    super.setAsConstructor();
    ChannelPartInfo.setAsConstructor_self.call( this, inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough );
    return this;
  }

  /** @override */
  static setAsConstructor_self( inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough ) {
    this.inChannelBegin = inChannelBegin;
    this.inChannelEnd = inChannelEnd;
    this.outputChannelCount = outputChannelCount;
    this.bPassThrough = bPassThrough;
  }

  /** @override */
  disposeResources() {
    this.bPassThrough = undefined;
    this.outputChannelCount = undefined;
    this.inChannelEnd = undefined;
    this.inChannelBegin = undefined;
    super.disposeResources();
  }

}

/**
 * Describe a range for a (pointwise) filters and a biases.
 *
 * It is an array of ChannelPartInfo. Every element describes input-output relationship of this parts. It owns and will
 * release these ChannelPartInfo.
 *
 */
class FiltersBiasesPartInfo extends Recyclable.OwnerArray {

  /**
   * Used as default Pointwise.FiltersBiasesPartInfo provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "Pointwise.FiltersBiasesPartInfo.Pool", FiltersBiasesPartInfo, FiltersBiasesPartInfo.setAsConstructor );

  /**
   * Every element of restArgs should be instance of ChannelPartInfo (even if restArgs has only one element).
   *
   * Note: This behavior is different from original Array which will views the argement is length (not element) if only one argument
   *       is given.
   */
  constructor( ...restArgs ) {
    super( ...restArgs );
    FiltersBiasesPartInfo.setAsConstructor_self.call( this );
  }

  /** @override */
  static setAsConstructor( ...restArgs ) {
    super.setAsConstructor( ...restArgs );
    FiltersBiasesPartInfo.setAsConstructor_self.call( this );
    return this;
  }

  /** @override */
  static setAsConstructor() {
    // Do nothing.
  }

  /** @override */
  disposeResources() {
    super.disposeResources();
  }

}

<commit_msg>Update Pointwise_ChannelPartInfo.js<commit_after>export { ChannelPartInfo };
export { FiltersBiasesPartInfo };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";

/**
 * Half channels information. Describe channel index range of lower half or higher half.
 *
 * @member {number} inChannelBegin
 *   The beginning input channel index of this part.
 *
 * @member {number} inChannelEnd
 *   The ending input channel index of this part.
 *
 * @member {number} outputChannelCount
 *   The channel count of output.
 *
 * @member {boolean} bPassThrough
 *   If true, this is a pass-through part and it will pass-through input channel index in [ inChannelBegin, inChannelEnd ) to output.
 * Otherwise, this is a non-pass-through part and it will using filters and biases extracted from weights array to convolve input channel
 * index in [ inChannelBegin, inChannelEnd ) to output.
 */
class ChannelPartInfo extends Recyclable.Root {

  /**
   * Used as default Pointwise.ChannelPartInfo provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "Pointwise.ChannelPartInfo.Pool", ChannelPartInfo, ChannelPartInfo.setAsConstructor );

  /**
   */
  constructor( inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough ) {
    super();
    ChannelPartInfo.setAsConstructor_self.call( this, inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough );
  }

  /** @override */
  static setAsConstructor( inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough ) {
    super.setAsConstructor();
    ChannelPartInfo.setAsConstructor_self.call( this, inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough );
    return this;
  }

  /** @override */
  static setAsConstructor_self( inChannelBegin, inChannelEnd, outputChannelCount, bPassThrough ) {
    this.inChannelBegin = inChannelBegin;
    this.inChannelEnd = inChannelEnd;
    this.outputChannelCount = outputChannelCount;
    this.bPassThrough = bPassThrough;
  }

  /** @override */
  disposeResources() {
    this.bPassThrough = undefined;
    this.outputChannelCount = undefined;
    this.inChannelEnd = undefined;
    this.inChannelBegin = undefined;
    super.disposeResources();
  }

}

/**
 * Describe a range for a (pointwise) filters and a biases.
 *
 * It is an array of ChannelPartInfo. Every element describes input-output relationship of this parts. It owns and will
 * release these ChannelPartInfo.
 *
 */
class FiltersBiasesPartInfo extends Recyclable.OwnerArray {

  /**
   * Used as default Pointwise.FiltersBiasesPartInfo provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "Pointwise.FiltersBiasesPartInfo.Pool", FiltersBiasesPartInfo, FiltersBiasesPartInfo.setAsConstructor );

  /**
   * Every element of restArgs should be instance of ChannelPartInfo (even if restArgs has only one element).
   *
   * Note: This behavior is different from original Array which will views the argement is length (not element) if only one argument
   *       is given.
   */
  constructor( ...restArgs ) {
    super( ...restArgs );
    FiltersBiasesPartInfo.setAsConstructor_self.call( this );
  }

  /** @override */
  static setAsConstructor( ...restArgs ) {
    super.setAsConstructor( ...restArgs );
    FiltersBiasesPartInfo.setAsConstructor_self.call( this );
    return this;
  }

  /** @override */
  static setAsConstructor_self() {
    // Do nothing.
  }

  /** @override */
  disposeResources() {
    super.disposeResources();
  }

}

<|endoftext|>


<commit_before>import React from "react"
import Link from "gatsby-link"
import Helmet from "react-helmet"

export default class Index extends React.Component {
  render() {
    return (

Hi Mangos!

Welcome to your new Gatsby site!!??????!

Now go build something great.

        <Link to="/page-2/">Go to page 2</Link>

    )
  }
}
<commit_msg>for fetch<commit_after>import React from "react"
import Link from "gatsby-link"
import Helmet from "react-helmet"

export default class Index extends React.Component {
  render() {
    return (

Hi Mans!

Welcome to your new Gatsby site!!??????!

Now go build something great.

        <Link to="/page-2/">Go to page 2</Link>

    )
  }
}
<|endoftext|>


<commit_before>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import $C from '../deps/collection';
import Parser from './constructor';
import { any } from '../helpers/gcc';
import { scopeMod } from '../consts/regs';
import { B_OPEN, B_CLOSE } from '../consts/literals';
import { $args, $argsRes, $consts } from '../consts/cache';

const
	nullableRgxp = /[?|!]$/,
	nullableMap = {'!': false, '?': true};

/**
 * Returns an array of function arguments from a string
 *
 * @param {string} str - source string
 * @return {!Array<string>}
 */
Parser.prototype.getFnArgs = function (str) {
	const
		res = [];

	let
		pOpen = 0,
		arg = '';

	$C(str).forEach((el) => {
		if (pOpen ? B_OPEN[el] : el === '(') {
			pOpen++;
			res.isCallable = true;

			if (pOpen === 1) {
				return;
			}

		} else if (pOpen ? B_CLOSE[el] : el === ')') {
			pOpen--;

			if (!pOpen) {
				return false;
			}
		}

		if (el === ',' && pOpen === 1) {
			res.push(arg.trim());
			arg = '';
			return;
		}

		if (pOpen) {
			arg += el;
		}
	});

	if (pOpen) {
		this.error(`invalid "${this.name}" declaration`);
		return [];
	}

	if (arg) {
		res.push(arg.trim());
	}

	res.isCallable = Boolean(res.isCallable);
	return res;
};

/**
 * Searches and initialises function arguments from a string and returns an information object
 *
 * @param {string} str - source string
 * @param {?$$SnakeskinParserDeclFnArgsParams=} [opt_params] - additional parameters:
 *
 *   *) [dir] - directive name (template, block etc.)
 *   *) [tplName] - template name
 *   *) [parentTplName] - parent template name
 *   *) [fnName] - custom function name (for blocks)
 *
 * @return {$$SnakeskinParserDeclFnArgsResult}
 */
Parser.prototype.declFnArgs = function (str, opt_params) {
	const
		{dir, tplName = this.tplName, parentTplName, fnName} = any(opt_params || {}),
		{structure} = this;

	const
		argsList = this.getFnArgs(str),
		isLocalFunction = !dir || fnName;

	let
		scope = undefined,
		argsMap = {},
		parentArgs;

	// Initialise cache objects
	// for the specified block

	if (dir) {
		if (!$args[tplName]) {
			$args[tplName] = {};
			$argsRes[tplName] = {};
		}

		if (!$args[tplName][dir]) {
			$args[tplName][dir] = {};
			$argsRes[tplName][dir] = {};
		}

		if (fnName) {
			if (parentTplName && $args[parentTplName][dir]) {
				parentArgs = $args[parentTplName][dir][fnName];
			}

			const
				cache = $argsRes[tplName][dir][fnName];

			// If our parameters already exists in the cache,
			// then init local variables and return an information object
			if (cache) {
				$C(cache.list).forEach((el) => {
					structure.vars[el[2]] = {
						scope: this.scope.length,
						value: el[0]
					};
				});

				if (cache.scope) {
					this.scope.push(cache.scope);
					this.structure.params['@scope'] = true;
				}

				return cache;
			}

			argsMap = $args[tplName][dir][fnName] = {};

		} else {
			if (parentTplName) {
				parentArgs = $args[parentTplName][dir];
			}

			argsMap = $args[tplName][dir];
		}
	}

	// Analise requested parameters
	// and save it in cache
	$C(argsList).forEach((el, i) => {
		const
			arg = el.split(/\s*=\s*/);

		if (arg.length > 1) {
			arg[1] = arg.slice(1).join('=');
			arg.splice(2, arg.length);
		}

		let defFilter = '';
		if (arg[0][0] === '(') {
			arg[0] = arg[0].replace(/^\(\s*([^|]+)(.*?)\)$/, (str, arg, filter) => {
				defFilter = filter;
				return arg;
			});
		}

		if (scopeMod.test(arg[0])) {
			// Scope already defined
			if (scope) {
				this.error(`invalid "${this.name}" declaration`);
				return {
					decl: '',
					def: '',
					isCallable: false,
					list: [],
					scope: undefined
				};
			}

			scope = arg[0] = arg[0]
				.replace(scopeMod, '');

			scope = scope
				.replace(nullableRgxp, '');
		}

		let nullable = undefined;
		arg[0] = arg[0].replace(nullableRgxp, (str) => {
			nullable = nullableMap[str];
			return '';
		});

		// Put to cache
		argsMap[arg[0]] = {
			defFilter,
			i,
			key: arg[0],
			nullable,
			scope,
			value: arg[1] && this.pasteDangerBlocks(arg[1].trim())
		};
	});

	if (dir) {
		// Mix the requested parameters
		// with parent block parameters
		$C(parentArgs).forEach((el, key) => {
			const
				arg = argsMap[key];

			// Parameter exists in a parent function
			if (arg) {
				arg.defFilter = el.defFilter + arg.defFilter;

				if (!scope && el.scope) {
					scope = el.scope;
					arg.scope = scope;
				}

				if (arg.nullable === undefined) {
					arg.nullable = el.nullable;
				}

				if (arg.nullable === undefined) {
					arg.nullable = el.nullable;
				}

				if (arg.value === undefined) {
					argsMap[key].value = el.value;
				}

				// Parameter doesn't exists in a parent function,
				// set it as a local variable
			} else {
				argsMap[key] = {
					defFilter: el.defFilter,
					i: el.i,
					key,
					local: true,
					value: el.value !== undefined ? el.value : 'undefined'
				};
			}
		});
	}

	const
		finalArgsList = [],
		localsList = [];

	$C(argsMap).forEach((el) => {
		if (el.local) {
			localsList[el.i] = el;

		} else {
			finalArgsList[el.i] = el;
		}
	});

	let
		decl = '',
		def = '';

	const
		locals = [];

	// Initialise local variables
	$C(localsList).forEach((el) => {
		if (!el) {
			return;
		}

		const
			old = el.key;

		if (isLocalFunction) {
			el.key = this.declVar(el.key, {fn: true});
		}

		locals.push([
			el.key,
			el.value,
			old
		]);

		def += `var ${el.key} = ${this.out(this.replaceDangerBlocks(el.value) + el.defFilter, {unsafe: true})};`;
		structure.vars[el.key] = {
			scope: this.scope.length,
			value: el.key
		};
	});

	const
		args = [],
		consts = $consts[tplName],
		constsCache = structure.params['@consts'] = {};

	// Initialise arguments
	$C(finalArgsList).forEach((el, i) => {
		const
			old = el.key;

		if (consts && consts[old] && isLocalFunction) {
			constsCache[old] = consts[old];
			delete consts[old];
		}

		if (isLocalFunction) {
			el.key = this.declVar(el.key, {fn: true});
		}

		decl += el.key;
		args.push([
			el.key,
			el.value,
			old
		]);

		const
			val = this.out(el.key + el.defFilter, {skipFirstWord: true, unsafe: true});

		if (el.value !== undefined) {
			const defVal = this.out(this.replaceDangerBlocks(el.value) + el.defFilter, {unsafe: true});
			def += `${el.key} = ${el.key} ${el.nullable ? '!== undefined' : '!= null'} ? ${val} : ${defVal};`;

		} else if (el.defFilter) {
			def += `${el.key} = ${val};`;
		}

		if (i !== finalArgsList.length - 1) {
			decl += ',';
		}
	});

	const res = {
		decl,
		def,
		isCallable: argsList.isCallable,
		list: args.concat(locals),
		scope
	};

	if (scope) {
		this.scope.push(scope);
		this.structure.params['@scope'] = true;
	}

	if (dir && fnName) {
		$argsRes[tplName][dir][fnName] = res;
	}

	return res;
};
<commit_msg>Optimisation<commit_after>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import Parser from './constructor';
import { any } from '../helpers/gcc';
import { scopeMod } from '../consts/regs';
import { B_OPEN, B_CLOSE } from '../consts/literals';
import { $args, $argsRes, $consts } from '../consts/cache';

const
	nullableRgxp = /[?|!]$/,
	nullableMap = {'!': false, '?': true};

/**
 * Returns an array of function arguments from a string
 *
 * @param {string} str - source string
 * @return {!Array<string>}
 */
Parser.prototype.getFnArgs = function (str) {
	const
		res = [];

	let
		pOpen = 0,
		arg = '';

	for (let i = 0; i < str.length; i++) {
		const
			el = str[i];

		if (pOpen ? B_OPEN[el] : el === '(') {
			pOpen++;
			res.isCallable = true;

			if (pOpen === 1) {
				continue;
			}

		} else if (pOpen ? B_CLOSE[el] : el === ')') {
			pOpen--;

			if (!pOpen) {
				break;
			}
		}

		if (el === ',' && pOpen === 1) {
			res.push(arg.trim());
			arg = '';
			continue;
		}

		if (pOpen) {
			arg += el;
		}
	}

	if (pOpen) {
		this.error(`invalid "${this.name}" declaration`);
		return [];
	}

	if (arg) {
		res.push(arg.trim());
	}

	res.isCallable = Boolean(res.isCallable);
	return res;
};

/**
 * Searches and initialises function arguments from a string and returns an information object
 *
 * @param {string} str - source string
 * @param {?$$SnakeskinParserDeclFnArgsParams=} [opt_params] - additional parameters:
 *
 *   *) [dir] - directive name (template, block etc.)
 *   *) [tplName] - template name
 *   *) [parentTplName] - parent template name
 *   *) [fnName] - custom function name (for blocks)
 *
 * @return {$$SnakeskinParserDeclFnArgsResult}
 */
Parser.prototype.declFnArgs = function (str, opt_params) {
	const
		{dir, tplName = this.tplName, parentTplName, fnName} = any(opt_params || {}),
		{structure} = this;

	const
		argsList = this.getFnArgs(str),
		isLocalFunction = !dir || fnName;

	let
		scope = undefined,
		argsMap = {},
		parentArgs;

	// Initialise cache objects
	// for the specified block
	if (dir) {
		if (!$args[tplName]) {
			$args[tplName] = {};
			$argsRes[tplName] = {};
		}

		if (!$args[tplName][dir]) {
			$args[tplName][dir] = {};
			$argsRes[tplName][dir] = {};
		}

		if (fnName) {
			if (parentTplName && $args[parentTplName][dir]) {
				parentArgs = $args[parentTplName][dir][fnName];
			}

			const
				cache = $argsRes[tplName][dir][fnName];

			// If our parameters already exists in the cache,
			// then init local variables and return an information object
			if (cache) {
				const
					{list} = cache;

				for (let i = 0; i < list.length; i++) {
					const
						el = list[i];

					structure.vars[el[2]] = {
						scope: this.scope.length,
						value: el[0]
					};
				}

				if (cache.scope) {
					this.scope.push(cache.scope);
					this.structure.params['@scope'] = true;
				}

				return cache;
			}

			argsMap = $args[tplName][dir][fnName] = {};

		} else {
			if (parentTplName) {
				parentArgs = $args[parentTplName][dir];
			}

			argsMap = $args[tplName][dir];
		}
	}

	// Analise requested parameters
	// and save it in cache
	for (let i = 0; i < argsList.length; i++) {
		const
			el = argsList[i],
			arg = el.split(/\s*=\s*/);

		if (arg.length > 1) {
			arg[1] = arg.slice(1).join('=');
			arg.splice(2, arg.length);
		}

		let defFilter = '';
		if (arg[0][0] === '(') {
			arg[0] = arg[0].replace(/^\(\s*([^|]+)(.*?)\)$/, (str, arg, filter) => {
				defFilter = filter;
				return arg;
			});
		}

		if (scopeMod.test(arg[0])) {
			if (scope) {
				this.error(`invalid "${this.name}" declaration`);
				return {
					decl: '',
					def: '',
					isCallable: false,
					list: [],
					scope: undefined
				};
			}

			scope = arg[0] = arg[0]
				.replace(scopeMod, '');

			scope = scope
				.replace(nullableRgxp, '');
		}

		let nullable = undefined;
		arg[0] = arg[0].replace(nullableRgxp, (str) => {
			nullable = nullableMap[str];
			return '';
		});

		argsMap[arg[0]] = {
			defFilter,
			i,
			key: arg[0],
			nullable,
			scope,
			value: arg[1] && this.pasteDangerBlocks(arg[1].trim())
		};
	}

	if (dir) {
		// Mix the requested parameters
		// with parent block parameters
		for (let key in parentArgs) {
			if (!parentArgs.hasOwnProperty(key)) {
				break;
			}

			const
				el = parentArgs[key],
				arg = argsMap[key];

			// Parameter exists in a parent function
			if (arg) {
				arg.defFilter = el.defFilter + arg.defFilter;

				if (!scope && el.scope) {
					scope = el.scope;
					arg.scope = scope;
				}

				if (arg.nullable === undefined) {
					arg.nullable = el.nullable;
				}

				if (arg.nullable === undefined) {
					arg.nullable = el.nullable;
				}

				if (arg.value === undefined) {
					argsMap[key].value = el.value;
				}

			// Parameter doesn't exists in a parent function,
			// set it as a local variable
			} else {
				argsMap[key] = {
					defFilter: el.defFilter,
					i: el.i,
					key,
					local: true,
					value: el.value !== undefined ? el.value : 'undefined'
				};
			}
		}
	}

	const
		finalArgsList = [],
		localsList = [];

	for (let key in argsMap) {
		if (!argsMap.hasOwnProperty(key)) {
			break;
		}

		const
			el = argsMap[key];

		if (el.local) {
			localsList[el.i] = el;

		} else {
			finalArgsList[el.i] = el;
		}
	}

	let
		decl = '',
		def = '';

	const
		locals = [];

	// Initialise local variables
	for (let i = 0; i < localsList.length; i++) {
		const
			el = localsList[i];

		if (!el) {
			continue;
		}

		const
			old = el.key;

		if (isLocalFunction) {
			el.key = this.declVar(el.key, {fn: true});
		}

		locals.push([
			el.key,
			el.value,
			old
		]);

		def += `var ${el.key} = ${this.out(this.replaceDangerBlocks(el.value) + el.defFilter, {unsafe: true})};`;
		structure.vars[el.key] = {
			scope: this.scope.length,
			value: el.key
		};
	}

	const
		args = [],
		consts = $consts[tplName],
		constsCache = structure.params['@consts'] = {};

	// Initialise arguments
	for (let i = 0; i < finalArgsList.length; i++) {
		const
			el = finalArgsList[i],
			old = el.key;

		if (consts && consts[old] && isLocalFunction) {
			constsCache[old] = consts[old];
			delete consts[old];
		}

		if (isLocalFunction) {
			el.key = this.declVar(el.key, {fn: true});
		}

		decl += el.key;
		args.push([
			el.key,
			el.value,
			old
		]);

		const
			val = this.out(el.key + el.defFilter, {skipFirstWord: true, unsafe: true});

		if (el.value !== undefined) {
			const defVal = this.out(this.replaceDangerBlocks(el.value) + el.defFilter, {unsafe: true});
			def += `${el.key} = ${el.key} ${el.nullable ? '!== undefined' : '!= null'} ? ${val} : ${defVal};`;

		} else if (el.defFilter) {
			def += `${el.key} = ${val};`;
		}

		if (i !== finalArgsList.length - 1) {
			decl += ',';
		}
	}

	const res = {
		decl,
		def,
		isCallable: argsList.isCallable,
		list: args.concat(locals),
		scope
	};

	if (scope) {
		this.scope.push(scope);
		this.structure.params['@scope'] = true;
	}

	if (dir && fnName) {
		$argsRes[tplName][dir][fnName] = res;
	}

	return res;
};
<|endoftext|>


<commit_before>var moment = require('moment'),
    logger = require('npmlog'),
    Datastore = require('nedb'),
    fs = require('fs'),
    Path = require('path');

var Settings = require('../settings'),
    PluginLoader = require('./plugins'),
    settings = new Settings(),
    Processor = require('./processor'),
    Engine = require('./engine'),
    EngineExtensions = require('./engine_extensions');

var db = new Datastore({ filename: Settings.storagePath(), autoload: true });
var slackUrlSeparator = /<(.*)>/;
var daysDelta = 6,
    now = Date.now(),
    past = moment(now).subtract(daysDelta, 'days').toDate().valueOf();

if(settings.loggerLevel) {
    logger.level = settings.loggerLevel;
}

logger.info('parser', 'Trying to load plugins...');
var pluginLoader = new PluginLoader(settings, logger),
    loadable = pluginLoader.listPlugins(),
    plugins = loadable
        .map((p) => pluginLoader.loadPlugin(p))
        .filter((p) => p)
        .sort((a, b) => a.constructor.priority - b.constructor.priority)
        .sort((a) => a.constructor.isUrlTransformer ? 0 : 1);

logger.verbose('parser', 'Loaded plugins: ', plugins.map(p => p.constructor.name).join(', '));

var m_f = moment(past),
    m_t = moment(now),
    m_format = 'MMMM DD';
logger.info('parser', `Querying data store for messages between ${m_f.format(m_format)} and ${m_t.format(m_format)}`);

db.find({ date: { $lte: now, $gte: past } }, function(error, docs) {
    if(!!error) {
        logger.error('parser', 'Error querying datastore: ', error);
        process.exit(1);
    }
    logger.info('parser', `Acquired ${docs.length} document(s)`);
    logger.verbose('parser', 'Filtering results using silencer reactions...');
    docs = docs.filter((d) => !settings.silencerEmojis.some((e) => d.text.indexOf(e) > -1));
    logger.info('parser', 'Ensuring documents are sane...');
    docs = docs.filter((d) => d.text.match(settings.messageMatcherRegex));
    logger.info('parser', `Result: ${docs.length} document(s)`);
    if(docs.length < 1) {
        logger.info('parser', 'Nothing to do.');
        process.exit(1);
    }
    docs = docs.map((d) => {
        var url = d.text.match(settings.messageMatcherRegex)[0],
            match = slackUrlSeparator.exec(url);
        if(match) {
            url = match[1];
        }
        return [
            url,
            d
        ];
    });
    var processor = new Processor(settings, logger, plugins, docs);
    processor.process((err, result) => {
        var en = new Engine(),
            ex = new EngineExtensions(logger);
        ex.registerExtensionsOn(en.getEnvironment());
        var html = '';
        try {
            html = en.build('index.html', result);
        } catch(ex) {
            logger.error('RenderEngine', 'Failed: ', ex);
        }
        if(html.length) {
            var target = Path.join(__dirname, 'test.html');
            fs.writeFileSync(target, html);
            logger.info('RenderEngine', `Wrote result to ${target}`);
        }
    });
});
<commit_msg>Update parser to accept command-line parameters<commit_after>var moment = require('moment'),
    logger = require('npmlog'),
    Datastore = require('nedb'),
    program = require('commander'),
    fs = require('fs'),
    Path = require('path');

var Settings = require('../settings'),
    PluginLoader = require('./plugins'),
    settings = new Settings(),
    Processor = require('./processor'),
    Engine = require('./engine'),
    EngineExtensions = require('./engine_extensions');

program
    .option('-o, --output <file>', 'Where to output the result file')
    .option('-t, --template [name]', 'Which template to use. Parser looks for template files on it\'s "templates" folder (src/parser/templates). Defaults to [default]', 'default')
    .option('-v, --verbose', 'Wether to run this utility in verbose mode or not.')
    .parse(process.argv);

var db = new Datastore({ filename: Settings.storagePath(), autoload: true });
var slackUrlSeparator = /<(.*)>/;
var daysDelta = 6,
    now = Date.now(),
    past = moment(now).subtract(daysDelta, 'days').toDate().valueOf(),
    targetFile;

if(settings.loggerLevel) {
    logger.level = settings.loggerLevel;
}

if(program.verbose) {
    logger.level = 'verbose';
    logger.verbose('parser', 'Verbose mode.');
}

if(!program.output) {
    logger.error('parser', 'You must provide an output destination write the parsing result.');
    process.exit(1);
} else {
    targetFile = Path.resolve(process.cwd(), program.output);
    try {
        var stat = fs.statSync(targetFile);
        if(!stat.isFile()) {
            logger.error('parser', 'Output path is not a file.');
            process.exit(1);
        }
    } catch(ex) {
        if(ex.code === 'ENOENT') {
            // Okay!
        } else {
            logger.error('parser', 'Error checking output dir: ', ex);
            // Oh dear...
            process.exit(1);
        }
    }
}

try {
    var stat = fs.statSync(Path.join(__dirname, 'templates', `${program.template}.html`));
    if(!stat.isFile()) {
        logger.error('parser', 'Template file if not a regular file: ', program.template);
        process.exit(1);
    }
} catch(ex) {
    if(ex.code === 'ENOENT') {
        logger.error('parser', 'Template file does not exist: ', program.template);
    } else {
        logger.error('parser', 'Error checking template file: ', ex);
    }
    process.exit(1);
}

logger.info('parser', 'Trying to load plugins...');
var pluginLoader = new PluginLoader(settings, logger),
    loadable = pluginLoader.listPlugins(),
    plugins = loadable
        .map((p) => pluginLoader.loadPlugin(p))
        .filter((p) => p)
        .sort((a, b) => a.constructor.priority - b.constructor.priority)
        .sort((a) => a.constructor.isUrlTransformer ? 0 : 1);

logger.verbose('parser', 'Loaded plugins: ', plugins.map(p => p.constructor.name).join(', '));

var m_f = moment(past),
    m_t = moment(now),
    m_format = 'MMMM DD';

logger.info('parser', `Querying data store for messages between ${m_f.format(m_format)} and ${m_t.format(m_format)}`);

db.find({ date: { $lte: now, $gte: past } }, function(error, docs) {
    if(!!error) {
        logger.error('parser', 'Error querying datastore: ', error);
        process.exit(1);
    }
    logger.info('parser', `Acquired ${docs.length} document(s)`);
    logger.verbose('parser', 'Filtering results using silencer reactions...');
    docs = docs.filter((d) => !settings.silencerEmojis.some((e) => d.text.indexOf(e) > -1));
    logger.info('parser', 'Ensuring documents are sane...');
    docs = docs.filter((d) => d.text.match(settings.messageMatcherRegex));
    logger.info('parser', `Result: ${docs.length} document(s)`);
    if(docs.length < 1) {
        logger.info('parser', 'Nothing to do.');
        process.exit(1);
    }
    docs = docs.map((d) => {
        var url = d.text.match(settings.messageMatcherRegex)[0],
            match = slackUrlSeparator.exec(url);
        if(match) {
            url = match[1];
        }
        return [
            url,
            d
        ];
    });
    var processor = new Processor(settings, logger, plugins, docs);
    processor.process((err, result) => {
        var en = new Engine(),
            ex = new EngineExtensions(logger);
        ex.registerExtensionsOn(en.getEnvironment());
        var html = '';
        try {
            html = en.build(`${program.template}.html`, result);
        } catch(ex) {
            logger.error('RenderEngine', 'Failed: ', ex);
        }
        if(html.length) {
            fs.writeFileSync(targetFile, html);
            logger.info('RenderEngine', `Wrote result to ${targetFile}`);
        }
    });
});
<|endoftext|>


<commit_before>export function parsePatch(uniDiff, options = {}) {
  let diffstr = uniDiff.split('\n'),
      list = [],
      i = 0;

  function parseIndex() {
    let index = {};
    list.push(index);

    // Ignore any leading junk
    while (i < diffstr.length) {
      if ((/^Index:/.test(diffstr[i])) || (/^@@/.test(diffstr[i]))) {
        break;
      }
      i++;
    }

    let header = (/^Index: (.*)/.exec(diffstr[i]));
    if (header) {
      index.index = header[1];
      i++;

      if (/^===/.test(diffstr[i])) {
        i++;
      }

      parseFileHeader(index);
      parseFileHeader(index);
    } else {
      // Ignore erant header components that might occur at the start of the file
      parseFileHeader({});
      parseFileHeader({});
    }

    index.hunks = [];

    while (i < diffstr.length) {
      if (/^Index:/.test(diffstr[i])) {
        break;
      } else if (/^@@/.test(diffstr[i])) {
        index.hunks.push(parseHunk());
      } else if (diffstr[i] && options.strict) {
        // Ignore unexpected content unless in strict mode
        throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(diffstr[i]));
      } else {
        i++;
      }
    }
  }

  // Parses the --- and +++ headers, if none are found, no lines
  // are consumed.
  function parseFileHeader(index) {
    let fileHeader = (/^(\-\-\-|\+\+\+)\s(\S+)\s?(.*)/.exec(diffstr[i]));
    if (fileHeader) {
      let keyPrefix = fileHeader[1] === '---' ? 'old' : 'new';
      index[keyPrefix + 'FileName'] = fileHeader[2];
      index[keyPrefix + 'Header'] = fileHeader[3];

      i++;
    }
  }

  // Parses a hunk
  // This assumes that we are at the start of a hunk.
  function parseHunk() {
    let chunkHeaderIndex = i,
        chunkHeaderLine = diffstr[i++],
        chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);

    let hunk = {
      oldStart: +chunkHeader[1],
      oldLines: +chunkHeader[2] || 1,
      newStart: +chunkHeader[3],
      newLines: +chunkHeader[4] || 1,
      lines: []
    };

    let addCount = 0,
        removeCount = 0;
    for (; i < diffstr.length; i++) {
      let operation = diffstr[i][0];

      if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
        hunk.lines.push(diffstr[i]);

        if (operation === '+') {
          addCount++;
        } else if (operation === '-') {
          removeCount++;
        } else if (operation === ' ') {
          addCount++;
          removeCount++;
        }
      } else {
        break;
      }
    }

    // Handle the empty block count case
    if (!addCount && hunk.newLines === 1) {
      hunk.newLines = 0;
    }
    if (!removeCount && hunk.oldLines === 1) {
      hunk.oldLines = 0;
    }

    // Perform optional sanity checking
    if (options.strict) {
      if (addCount !== hunk.newLines) {
        throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
      }
      if (removeCount !== hunk.oldLines) {
        throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
      }
    }

    return hunk;
  }

  while (i < diffstr.length) {
    parseIndex();
  }

  return list;
}
<commit_msg>Allow patchs in diff format<commit_after>export function parsePatch(uniDiff, options = {}) {
  let diffstr = uniDiff.split('\n'),
      list = [],
      i = 0;

  function parseIndex() {
    let index = {};
    list.push(index);

    // Ignore any leading junk
    while (i < diffstr.length) {
      if (/^(Index:|diff -r|@@)/.test(diffstr[i])) {
        break;
      }
      i++;
    }

    let header = (/^(?:Index:|diff -r (?:\w+)) (.*)/.exec(diffstr[i]));
    if (header) {
      index.index = header[1];
      i++;

      if (/^===/.test(diffstr[i])) {
        i++;
      }

      parseFileHeader(index);
      parseFileHeader(index);
    } else {
      // Ignore erant header components that might occur at the start of the file
      parseFileHeader({});
      parseFileHeader({});
    }

    index.hunks = [];

    while (i < diffstr.length) {
      if (/^(Index:|diff -r)/.test(diffstr[i])) {
        break;
      } else if (/^@@/.test(diffstr[i])) {
        index.hunks.push(parseHunk());
      } else if (diffstr[i] && options.strict) {
        // Ignore unexpected content unless in strict mode
        throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(diffstr[i]));
      } else {
        i++;
      }
    }
  }

  // Parses the --- and +++ headers, if none are found, no lines
  // are consumed.
  function parseFileHeader(index) {
    let fileHeader = (/^(\-\-\-|\+\+\+)\s(\S+)\s?(.*)/.exec(diffstr[i]));
    if (fileHeader) {
      let keyPrefix = fileHeader[1] === '---' ? 'old' : 'new';
      index[keyPrefix + 'FileName'] = fileHeader[2];
      index[keyPrefix + 'Header'] = fileHeader[3];

      i++;
    }
  }

  // Parses a hunk
  // This assumes that we are at the start of a hunk.
  function parseHunk() {
    let chunkHeaderIndex = i,
        chunkHeaderLine = diffstr[i++],
        chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);

    let hunk = {
      oldStart: +chunkHeader[1],
      oldLines: +chunkHeader[2] || 1,
      newStart: +chunkHeader[3],
      newLines: +chunkHeader[4] || 1,
      lines: []
    };

    let addCount = 0,
        removeCount = 0;
    for (; i < diffstr.length; i++) {
      let operation = diffstr[i][0];

      if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
        hunk.lines.push(diffstr[i]);

        if (operation === '+') {
          addCount++;
        } else if (operation === '-') {
          removeCount++;
        } else if (operation === ' ') {
          addCount++;
          removeCount++;
        }
      } else {
        break;
      }
    }

    // Handle the empty block count case
    if (!addCount && hunk.newLines === 1) {
      hunk.newLines = 0;
    }
    if (!removeCount && hunk.oldLines === 1) {
      hunk.oldLines = 0;
    }

    // Perform optional sanity checking
    if (options.strict) {
      if (addCount !== hunk.newLines) {
        throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
      }
      if (removeCount !== hunk.oldLines) {
        throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
      }
    }

    return hunk;
  }

  while (i < diffstr.length) {
    parseIndex();
  }

  return list;
}
<|endoftext|>


<commit_before>Modules.VERSION = '2.0.0';

this.menus = {
	get viewSidebarMenu () { return $('viewSidebarMenu'); },

	_ShortcutUtils: null,
	get ShortcutUtils () {
		if(!this._ShortcutUtils) {
			var temp = {};
			Cu.import("resource://gre/modules/ShortcutUtils.jsm", temp);
			this._ShortcutUtils = temp.ShortcutUtils;
		}
		return this._ShortcutUtils;
	},

	contextMenu: {
		get menu () { return $('toolbar-context-menu'); },
		get options () { return $(objName+'-contextOptions'); },
		get separator () { return $(objName+'-contextSeparator'); },

		handleEvent: function(e) {
			switch(e.type) {
				// Menus are dynamic, I need to make sure the entries do what they're supposed to if they're changed
				case 'popupshowing':
					var trigger = e.originalTarget.triggerNode;
					var hidden =	!isAncestor(trigger, mainSidebar.button)
							&& !isAncestor(trigger, mainSidebar.header)
							&& !isAncestor(trigger, twinSidebar.button)
							&& !isAncestor(trigger, twinSidebar.header);

					toggleAttribute(this.options, 'hidden', hidden);
					toggleAttribute(this.separator, 'hidden', hidden);

					menus.setMenuEntries(this.menu);
					break;
			}
		}
	},

	viewMenu: {
		get viewMenu () { return $('viewToolbarsMenu').firstChild; }, // View - Toolbars submenu

		handleEvent: function(e) {
			switch(e.type) {
				// Menus are dynamic, I need to make sure the entries do what they're supposed to if they're changed
				case 'popupshown':
					menus.setMenuEntries(this.menu);
					break;
			}
		}
	},

	customizeMenu: {
		get viewMenu () { return $('customization-toolbar-menu'); }, // View - Toolbars submenu

		handleEvent: function(e) {
			switch(e.type) {
				// Menus are dynamic, I need to make sure the entries do what they're supposed to if they're changed
				case 'popupshown':
					menus.setMenuEntries(this.menu);
					break;
			}
		}
	},

	handleEvent: function(e) {
		switch(e.type) {
			case 'popupshowing':
				this.menuItemsCheck(e.target);
				break;

			case 'mousedown':
				if(e.which != 1) { return; }
				this.openSidebarMenu($(e.target.getAttribute('TitleButton')));
				break;

			case 'endToggleSidebar':
				var bar = e.detail.bar;
				if(!bar.closed && bar.command.startsWith(objName+'-viewBlankSidebar')) {
					this.openSidebarMenu($((bar.twin) ? objName+'-openTwinSidebarMenu' : objName+'-openSidebarMenu'));
				}
				break;

		}
	},

	observe: function(aSubject, aTopic, aData) {
		switch(aSubject) {
			case 'titleButton':
				this.toggleMenuButton();
				break;

			case 'titleButtonTwin':
				this.toggleMenuButtonTwin();
				break;
		}
	},

	setMenuEntries: function(menu) {
		if(mainSidebar.toolbar) {
			setAttribute(menu.getElementsByAttribute('toolbarId', mainSidebar.toolbar.id)[0], 'command', mainSidebar.toolbar.getAttribute('menucommand'));
		}
		if(twinSidebar.toolbar) {
			setAttribute(menu.getElementsByAttribute('toolbarId', twinSidebar.toolbar.id)[0], 'command', twinSidebar.toolbar.getAttribute('menucommand'));
		}
	},

	populateSidebarMenu: function(menu, useButton) {
		while(menu.firstChild) {
			menu.firstChild.remove();
		}

		// Populate with Social API entries
		if(SocialSidebar.populateSidebarMenu) { SocialSidebar.populateSidebarMenu({ target: this.viewSidebarMenu }); }

		for(let child of this.viewSidebarMenu.childNodes) {
			// PanelUI styling is mostly done with toolbarbutton elements, so if I want to use the native styling, I have to use these nodes as well
			if(useButton && child.localName != 'menuseparator') {
				var newItem = document.createElement('toolbarbutton');
				for(let attr of child.attributes) {
					setAttribute(newItem, attr.name, attr.value);
				}
			} else {
				var newItem = child.cloneNode(true);
			}

			if(menu.id) {
				newItem.id = newItem.id+'_'+menu.id;
			}
			menu.appendChild(newItem);
		}

		this.menuItemsCheck(menu);
	},

	menuItemsCheck: function(menu) {
		var mainMenu = (menu == this.viewSidebarMenu);

		for(let child of menu.childNodes) {
			if(!child.getAttribute('observes')) {
				child.hidden = !SocialSidebar.canShow;
				if(child.getAttribute('origin')) {
					if(child.getAttribute('oncommand').contains('show')) {
						var command = ((!UNLOADED) ? objName+'.Social.placeSidebar(this); ' : '')+"SocialSidebar.show(this.getAttribute('origin'));";
						setAttribute(child, 'oncommand', command);
					} else {
						var command = (!UNLOADED) ? objName+'.Social.ensureSwitchBeforeHide(this); ' : 'SocialSidebar.hide();';
						setAttribute(child, 'oncommand', command);
					}
				}
			}

			if(mainMenu) { continue; }

			// No point in having this menu entry in our lists if it isn't going to be visible
			if(child.hidden || child.collapsed) {
				child.remove();
				continue;
			}

			// if we're in the mini panel, let's try to style it like a native PanelUI-subView panel
			if((menu == panel.menu || menu == panel.viewMenu) && child.localName != 'menuseparator') {
				child.classList.add('subviewbutton');

				// add keyboard shortcuts, as it doesn't display them automatically in panels
				if(child.getAttribute('acceltext')) {
					setAttribute(child, 'shortcut', child.getAttribute('acceltext'));
				} else if(child.getAttribute('key')) {
					var menuKey = $(child.getAttribute('key'));
					if(menuKey) {
						setAttribute(child, 'shortcut', this.ShortcutUtils.prettifyShortcut(menuKey));
					}
				}
			}
		}
	},

	openSidebarMenu: function(menu) {
		var target = $(menu.getAttribute('target'));

		setAttribute(target, 'active', 'true');
		if(!target.getAttribute('TitleButton')) { setAttribute(target, 'TitleButton', 'true'); }

		// the title needs to be visible to place the menu correctly
		headers.toggleTitles();
		headers.toggleHeaders();
		menu.style.minWidth = target.clientWidth +'px';

		menu.openPopup(target, 'after_start');
		dispatch(target, { type: 'openSidebarMenu', cancelable: false });
	},

	closeSidebarMenu: function(menu) {
		var bar = (trueAttribute(menu, 'twinSidebar')) ? twinSidebar : mainSidebar;

		if(bar.twin) {
			this.toggleMenuButtonTwin();
		} else {
			this.toggleMenuButton();
		}

		var target = $(menu.getAttribute('target'));
		target.removeAttribute('active');

		headers.toggleTitles();
		headers.toggleHeaders();

		dispatch(target, { type: 'closeSidebarMenu', cancelable: false });

		// the aSync is probably unnecessary, but I think it'll work better and it'll be smoother
		aSync(function() {
			if(bar.closed) { return; }
			var command = bar.command;
			if(command.startsWith(objName+'-viewBlankSidebar')) {
				SidebarUI.toggle(command, false, bar.twin);
			}
		});
	},

	toggleMenuButton: function() {
		if(UNLOADED || window.closed || window.willClose || !Prefs.titleButton) {
			removeAttribute(mainSidebar.titleNode, 'TitleButton');
			Listeners.remove(mainSidebar.titleNode, 'mousedown', this);
		} else {
			setAttribute(mainSidebar.titleNode, 'TitleButton', objName+'-openSidebarMenu');
			Listeners.add(mainSidebar.titleNode, 'mousedown', this);
		}
	},

	toggleMenuButtonTwin: function() {
		if(UNLOADED || window.closed || window.willClose || !Prefs.twinSidebar || !Prefs.titleButtonTwin) {
			removeAttribute(twinSidebar.titleNode, 'TitleButton');
			Listeners.remove(twinSidebar.titleNode, 'mousedown', this);
		} else {
			setAttribute(twinSidebar.titleNode, 'TitleButton', objName+'-openTwinSidebarMenu');
			Listeners.add(twinSidebar.titleNode, 'mousedown', this);
		}
	}
};

Modules.LOADMODULE = function() {
	Overlays.overlayURI('chrome://'+objPathString+'/content/headers.xul', 'menus');
	Overlays.overlayURI('chrome://'+objPathString+'/content/headersTwin.xul', 'menusTwin');

	Listeners.add(menus.contextMenu.menu, 'popupshowing', menus.contextMenu);
	Listeners.add(menus.viewMenu.menu, 'popupshown', menus.viewMenu);
	Listeners.add(menus.customizeMenu.menu, 'popupshown', menus.customizeMenu);
	Listeners.add($('social-statusarea-popup'), 'popupshowing', menus);
	Listeners.add(window, 'endToggleSidebar', menus);

	SidebarUI.triggers.twin.set('viewTwinSidebarMenuMenu', function() { return $(objName+'-viewTwinSidebarMenuMenu'); });
	SidebarUI.triggers.twin.set('menuTitleTwin', function() { return $(objName+'-openTwinSidebarMenu'); });

	SidebarUI.triggers.barSwitch.set('viewSidebarMenuMenu', function() { return $('viewSidebarMenuMenu'); });
	SidebarUI.triggers.barSwitch.set('viewTwinSidebarMenuMenu', function() { return $(objName+'-viewTwinSidebarMenuMenu'); });
	SidebarUI.triggers.barSwitch.set('menuTitle', function() { return $(objName+'-openSidebarMenu'); });
	SidebarUI.triggers.barSwitch.set('menuTitleTwin', function() { return $(objName+'-openTwinSidebarMenu'); });

	Prefs.listen('titleButton', menus);
	Prefs.listen('titleButtonTwin', menus);

	menus.toggleMenuButton();
	menus.toggleMenuButtonTwin();
};

Modules.UNLOADMODULE = function() {
	SidebarUI.triggers.twin.delete('viewTwinSidebarMenuMenu');
	SidebarUI.triggers.twin.delete('menuTitleTwin');

	SidebarUI.triggers.barSwitch.delete('viewSidebarMenuMenu');
	SidebarUI.triggers.barSwitch.delete('viewTwinSidebarMenuMenu');
	SidebarUI.triggers.barSwitch.delete('menuTitle');
	SidebarUI.triggers.barSwitch.delete('menuTitleTwin');

	Prefs.unlisten('titleButton', menus);
	Prefs.unlisten('titleButtonTwin', menus);

	Listeners.remove(menus.contextMenu.menu, 'popupshowing', menus.contextMenu);
	Listeners.remove(menus.viewMenu.menu, 'popupshown', menus.viewMenu);
	Listeners.remove(menus.customizeMenu.menu, 'popupshown', menus.customizeMenu);
	Listeners.remove($('social-statusarea-popup'), 'popupshowing', menus);
	Listeners.remove(window, 'endToggleSidebar', menus);

	// ensure the menu is properly reset when unloading
	menus.menuItemsCheck(menus.viewSidebarMenu);
	if($('social-statusarea-popup')) { menus.menuItemsCheck($('social-statusarea-popup')); }

	menus.toggleMenuButton();
	menus.toggleMenuButtonTwin();

	if(UNLOADED) {
		Overlays.removeOverlayURI('chrome://'+objPathString+'/content/headers.xul', 'menus');
		Overlays.removeOverlayURI('chrome://'+objPathString+'/content/headersTwin.xul', 'menusTwin');
	}
};
<commit_msg>#81 fixing mixing bookmarks menu label again<commit_after>Modules.VERSION = '2.0.1';

this.menus = {
	get viewSidebarMenu () { return $('viewSidebarMenu'); },

	_ShortcutUtils: null,
	get ShortcutUtils () {
		if(!this._ShortcutUtils) {
			var temp = {};
			Cu.import("resource://gre/modules/ShortcutUtils.jsm", temp);
			this._ShortcutUtils = temp.ShortcutUtils;
		}
		return this._ShortcutUtils;
	},

	contextMenu: {
		get menu () { return $('toolbar-context-menu'); },
		get options () { return $(objName+'-contextOptions'); },
		get separator () { return $(objName+'-contextSeparator'); },

		handleEvent: function(e) {
			switch(e.type) {
				// Menus are dynamic, I need to make sure the entries do what they're supposed to if they're changed
				case 'popupshowing':
					var trigger = e.originalTarget.triggerNode;
					var hidden =	!isAncestor(trigger, mainSidebar.button)
							&& !isAncestor(trigger, mainSidebar.header)
							&& !isAncestor(trigger, twinSidebar.button)
							&& !isAncestor(trigger, twinSidebar.header);

					toggleAttribute(this.options, 'hidden', hidden);
					toggleAttribute(this.separator, 'hidden', hidden);

					menus.setMenuEntries(this.menu);
					break;
			}
		}
	},

	viewMenu: {
		get menu () { return $('viewToolbarsMenu').firstChild; }, // View - Toolbars submenu

		handleEvent: function(e) {
			switch(e.type) {
				// Menus are dynamic, I need to make sure the entries do what they're supposed to if they're changed
				case 'popupshown':
					menus.setMenuEntries(this.menu);
					break;
			}
		}
	},

	customizeMenu: {
		get menu () { return $('customization-toolbar-menu'); },

		handleEvent: function(e) {
			switch(e.type) {
				// Menus are dynamic, I need to make sure the entries do what they're supposed to if they're changed
				case 'popupshown':
					menus.setMenuEntries(this.menu);
					break;
			}
		}
	},

	socialStatusArea: {
		get menu () { return $('social-statusarea-popup'); },

		handleEvent: function(e) {
			switch(e.type) {
				case 'popupshowing':
					this.menuItemsCheck(e.target);
					break;
			}
		}
	},

	handleEvent: function(e) {
		switch(e.type) {
			case 'popupshowing':
				// the bookmarks sidebar menu entry has the annoying habit of losing its label during startup, for reasons...
				var bookmarksEntry = $('menu_bookmarksSidebar');
				var labelValue = $('viewBookmarksSidebar') && $('viewBookmarksSidebar').getAttribute('sidebartitle');
				if(bookmarksEntry && labelValue) {
					if(bookmarksEntry.getAttribute('label') != labelValue) {
						setAttribute(bookmarksEntry, 'label', labelValue);
					} else {
						Listeners.remove(window, 'popupshowing', this, true);
					}
				}
				break;

			case 'mousedown':
				if(e.which != 1) { return; }
				this.openSidebarMenu($(e.target.getAttribute('TitleButton')));
				break;

			case 'endToggleSidebar':
				var bar = e.detail.bar;
				if(!bar.closed && bar.command.startsWith(objName+'-viewBlankSidebar')) {
					this.openSidebarMenu($((bar.twin) ? objName+'-openTwinSidebarMenu' : objName+'-openSidebarMenu'));
				}
				break;
		}
	},

	observe: function(aSubject, aTopic, aData) {
		switch(aSubject) {
			case 'titleButton':
				this.toggleMenuButton();
				break;

			case 'titleButtonTwin':
				this.toggleMenuButtonTwin();
				break;
		}
	},

	setMenuEntries: function(menu) {
		if(mainSidebar.toolbar) {
			setAttribute(menu.getElementsByAttribute('toolbarId', mainSidebar.toolbar.id)[0], 'command', mainSidebar.toolbar.getAttribute('menucommand'));
		}
		if(twinSidebar.toolbar) {
			setAttribute(menu.getElementsByAttribute('toolbarId', twinSidebar.toolbar.id)[0], 'command', twinSidebar.toolbar.getAttribute('menucommand'));
		}
	},

	populateSidebarMenu: function(menu, useButton) {
		while(menu.firstChild) {
			menu.firstChild.remove();
		}

		// Populate with Social API entries
		if(SocialSidebar.populateSidebarMenu) { SocialSidebar.populateSidebarMenu({ target: this.viewSidebarMenu }); }

		for(let child of this.viewSidebarMenu.childNodes) {
			// PanelUI styling is mostly done with toolbarbutton elements, so if I want to use the native styling, I have to use these nodes as well
			if(useButton && child.localName != 'menuseparator') {
				var newItem = document.createElement('toolbarbutton');
				for(let attr of child.attributes) {
					setAttribute(newItem, attr.name, attr.value);
				}
			} else {
				var newItem = child.cloneNode(true);
			}

			if(menu.id) {
				newItem.id = newItem.id+'_'+menu.id;
			}
			menu.appendChild(newItem);
		}

		this.menuItemsCheck(menu);
	},

	menuItemsCheck: function(menu) {
		var mainMenu = (menu == this.viewSidebarMenu);

		for(let child of menu.childNodes) {
			if(!child.getAttribute('observes')) {
				child.hidden = !SocialSidebar.canShow;
				if(child.getAttribute('origin')) {
					if(child.getAttribute('oncommand').contains('show')) {
						var command = ((!UNLOADED) ? objName+'.Social.placeSidebar(this); ' : '')+"SocialSidebar.show(this.getAttribute('origin'));";
						setAttribute(child, 'oncommand', command);
					} else {
						var command = (!UNLOADED) ? objName+'.Social.ensureSwitchBeforeHide(this); ' : 'SocialSidebar.hide();';
						setAttribute(child, 'oncommand', command);
					}
				}
			}

			if(mainMenu) { continue; }

			// No point in having this menu entry in our lists if it isn't going to be visible
			if(child.hidden || child.collapsed) {
				child.remove();
				continue;
			}

			// if we're in the mini panel, let's try to style it like a native PanelUI-subView panel
			if((menu == panel.menu || menu == panel.viewMenu) && child.localName != 'menuseparator') {
				child.classList.add('subviewbutton');

				// add keyboard shortcuts, as it doesn't display them automatically in panels
				if(child.getAttribute('acceltext')) {
					setAttribute(child, 'shortcut', child.getAttribute('acceltext'));
				} else if(child.getAttribute('key')) {
					var menuKey = $(child.getAttribute('key'));
					if(menuKey) {
						setAttribute(child, 'shortcut', this.ShortcutUtils.prettifyShortcut(menuKey));
					}
				}
			}
		}
	},

	openSidebarMenu: function(menu) {
		var target = $(menu.getAttribute('target'));

		setAttribute(target, 'active', 'true');
		if(!target.getAttribute('TitleButton')) { setAttribute(target, 'TitleButton', 'true'); }

		// the title needs to be visible to place the menu correctly
		headers.toggleTitles();
		headers.toggleHeaders();
		menu.style.minWidth = target.clientWidth +'px';

		menu.openPopup(target, 'after_start');
		dispatch(target, { type: 'openSidebarMenu', cancelable: false });
	},

	closeSidebarMenu: function(menu) {
		var bar = (trueAttribute(menu, 'twinSidebar')) ? twinSidebar : mainSidebar;

		if(bar.twin) {
			this.toggleMenuButtonTwin();
		} else {
			this.toggleMenuButton();
		}

		var target = $(menu.getAttribute('target'));
		target.removeAttribute('active');

		headers.toggleTitles();
		headers.toggleHeaders();

		dispatch(target, { type: 'closeSidebarMenu', cancelable: false });

		// the aSync is probably unnecessary, but I think it'll work better and it'll be smoother
		aSync(function() {
			if(bar.closed) { return; }
			var command = bar.command;
			if(command.startsWith(objName+'-viewBlankSidebar')) {
				SidebarUI.toggle(command, false, bar.twin);
			}
		});
	},

	toggleMenuButton: function() {
		if(UNLOADED || window.closed || window.willClose || !Prefs.titleButton) {
			removeAttribute(mainSidebar.titleNode, 'TitleButton');
			Listeners.remove(mainSidebar.titleNode, 'mousedown', this);
		} else {
			setAttribute(mainSidebar.titleNode, 'TitleButton', objName+'-openSidebarMenu');
			Listeners.add(mainSidebar.titleNode, 'mousedown', this);
		}
	},

	toggleMenuButtonTwin: function() {
		if(UNLOADED || window.closed || window.willClose || !Prefs.twinSidebar || !Prefs.titleButtonTwin) {
			removeAttribute(twinSidebar.titleNode, 'TitleButton');
			Listeners.remove(twinSidebar.titleNode, 'mousedown', this);
		} else {
			setAttribute(twinSidebar.titleNode, 'TitleButton', objName+'-openTwinSidebarMenu');
			Listeners.add(twinSidebar.titleNode, 'mousedown', this);
		}
	}
};

Modules.LOADMODULE = function() {
	Overlays.overlayURI('chrome://'+objPathString+'/content/headers.xul', 'menus');
	Overlays.overlayURI('chrome://'+objPathString+'/content/headersTwin.xul', 'menusTwin');

	Listeners.add(window, 'endToggleSidebar', menus);
	Listeners.add(window, 'popupshowing', menus, true);
	Listeners.add(menus.contextMenu.menu, 'popupshowing', menus.contextMenu);
	Listeners.add(menus.viewMenu.menu, 'popupshown', menus.viewMenu);
	Listeners.add(menus.customizeMenu.menu, 'popupshown', menus.customizeMenu);
	Listeners.add(menus.socialStatusArea.menu, 'popupshowing', menus.socialStatusArea);

	SidebarUI.triggers.twin.set('viewTwinSidebarMenuMenu', function() { return $(objName+'-viewTwinSidebarMenuMenu'); });
	SidebarUI.triggers.twin.set('menuTitleTwin', function() { return $(objName+'-openTwinSidebarMenu'); });

	SidebarUI.triggers.barSwitch.set('viewSidebarMenuMenu', function() { return $('viewSidebarMenuMenu'); });
	SidebarUI.triggers.barSwitch.set('viewTwinSidebarMenuMenu', function() { return $(objName+'-viewTwinSidebarMenuMenu'); });
	SidebarUI.triggers.barSwitch.set('menuTitle', function() { return $(objName+'-openSidebarMenu'); });
	SidebarUI.triggers.barSwitch.set('menuTitleTwin', function() { return $(objName+'-openTwinSidebarMenu'); });

	Prefs.listen('titleButton', menus);
	Prefs.listen('titleButtonTwin', menus);

	menus.toggleMenuButton();
	menus.toggleMenuButtonTwin();
};

Modules.UNLOADMODULE = function() {
	SidebarUI.triggers.twin.delete('viewTwinSidebarMenuMenu');
	SidebarUI.triggers.twin.delete('menuTitleTwin');

	SidebarUI.triggers.barSwitch.delete('viewSidebarMenuMenu');
	SidebarUI.triggers.barSwitch.delete('viewTwinSidebarMenuMenu');
	SidebarUI.triggers.barSwitch.delete('menuTitle');
	SidebarUI.triggers.barSwitch.delete('menuTitleTwin');

	Prefs.unlisten('titleButton', menus);
	Prefs.unlisten('titleButtonTwin', menus);

	Listeners.remove(window, 'popupshowing', menus, true);
	Listeners.remove(window, 'endToggleSidebar', menus);
	Listeners.remove(menus.contextMenu.menu, 'popupshowing', menus.contextMenu);
	Listeners.remove(menus.viewMenu.menu, 'popupshown', menus.viewMenu);
	Listeners.remove(menus.customizeMenu.menu, 'popupshown', menus.customizeMenu);
	Listeners.remove(menus.socialStatusArea.menu, 'popupshowing', menus.socialStatusArea);

	// ensure the menu is properly reset when unloading
	menus.menuItemsCheck(menus.viewSidebarMenu);
	if(menus.socialStatusArea.menu) { menus.menuItemsCheck(menus.socialStatusArea.menu); }

	menus.toggleMenuButton();
	menus.toggleMenuButtonTwin();

	if(UNLOADED) {
		Overlays.removeOverlayURI('chrome://'+objPathString+'/content/headers.xul', 'menus');
		Overlays.removeOverlayURI('chrome://'+objPathString+'/content/headersTwin.xul', 'menusTwin');
	}
};
<|endoftext|>


<commit_before>/* eslint-disable no-unused-vars */
import { useMutation } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React from 'react'
import * as Yup from 'yup'

import { Table as EditableTable } from 'src/components/editableTable'
import { CashOut, CashIn } from 'src/components/inputs/cashbox/Cashbox'
import { NumberInput, CashCassetteInput } from 'src/components/inputs/formik'
import { fromNamespace } from 'src/utils/config'

import styles from './Cassettes.styles'

const useStyles = makeStyles(styles)

const widthsByNumberOfCassettes = {
  2: { cashbox: 116, cassette: 280, cassetteGraph: 80, editWidth: 174 },
  3: { cashbox: 106, cassette: 200, cassetteGraph: 60, editWidth: 145 },
  4: { cashbox: 106, cassette: 164, cassetteGraph: 40, editWidth: 90 }
}

const ValidationSchema = Yup.object().shape({
  name: Yup.string().required('Required'),
  cashbox: Yup.number()
    .label('Cashbox')
    .required()
    .integer()
    .min(0)
    .max(1000),
  cassette1: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500),
  cassette2: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500),
  cassette3: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500),
  cassette4: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500)
})

const SET_CASSETTE_BILLS = gql`
  mutation MachineAction(
    $deviceId: ID!
    $action: MachineAction!
    $cashbox: Int!
    $cassette1: Int!
    $cassette2: Int!
    $cassette3: Int!
    $cassette4: Int!
  ) {
    machineAction(
      deviceId: $deviceId
      action: $action
      cashbox: $cashbox
      cassette1: $cassette1
      cassette2: $cassette2
      cassette3: $cassette3
      cassette4: $cassette4
    ) {
      deviceId
      cashbox
      cassette1
      cassette2
      cassette3
      cassette4
    }
  }
`

const CashCassettes = ({ machine, config, refetchData }) => {
  const data = { machine, config }
  const classes = useStyles()

  const cashout = data?.config && fromNamespace('cashOut')(data.config)
  const locale = data?.config && fromNamespace('locale')(data.config)
  const fiatCurrency = locale?.fiatCurrency
  const numberOfCassettes = machine.numberOfCassettes

  const getCashoutSettings = deviceId => fromNamespace(deviceId)(cashout)
  const isCashOutDisabled = ({ deviceId }) =>
    !getCashoutSettings(deviceId).active

  const elements = [
    {
      name: 'cashbox',
      header: 'Cashbox',
      width: widthsByNumberOfCassettes[numberOfCassettes].cashbox,
      stripe: false,
      view: value => (
        <CashIn currency={{ code: fiatCurrency }} notes={value} total={0} />
      ),
      input: NumberInput,
      inputProps: {
        decimalPlaces: 0
      }
    }
  ]

  R.until(
    R.gt(R.__, numberOfCassettes),
    it => {
      elements.push({
        name: `cassette${it}`,
        header: `Cash-out ${it}`,
        width: widthsByNumberOfCassettes[numberOfCassettes].cassette,
        stripe: true,
        doubleHeader: 'Cash-out',
        view: value => {
          return (
            <CashOut
              className={classes.cashbox}
              denomination={
                getCashoutSettings(machine.deviceId)?.[`cassette${it}`]
              }
              currency={{ code: fiatCurrency }}
              notes={value}
              width={widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph}
            />
          )
        },
        isHidden: ({ numberOfCassettes }) => it > numberOfCassettes,
        input: CashCassetteInput,
        inputProps: {
          decimalPlaces: 0,
          width: widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph,
          inputClassName: classes.cashbox
        }
      })
      return R.add(1, it)
    },
    1
  )

  const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
    refetchQueries: () => refetchData()
  })

  const onSave = (
    ...[, { deviceId, cashbox, cassette1, cassette2, cassette3, cassette4 }]
  ) => {
    return setCassetteBills({
      variables: {
        action: 'setCassetteBills',
        deviceId: deviceId,
        cashbox,
        cassette1,
        cassette2,
        cassette3,
        cassette4
      }
    })
  }

  return machine.name ? (
    <EditableTable
      error={error?.message}
      enableEdit
      editWidth={widthsByNumberOfCassettes[numberOfCassettes].editWidth}
      stripeWhen={isCashOutDisabled}
      disableRowEdit={isCashOutDisabled}
      name="cashboxes"
      elements={elements}
      data={[machine]}
      save={onSave}
      validationSchema={ValidationSchema}
    />
  ) : null
}

export default CashCassettes
<commit_msg>fix: reenable eslint on file<commit_after>import { useMutation } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React from 'react'
import * as Yup from 'yup'

import { Table as EditableTable } from 'src/components/editableTable'
import { CashOut, CashIn } from 'src/components/inputs/cashbox/Cashbox'
import { NumberInput, CashCassetteInput } from 'src/components/inputs/formik'
import { fromNamespace } from 'src/utils/config'

import styles from './Cassettes.styles'

const useStyles = makeStyles(styles)

const widthsByNumberOfCassettes = {
  2: { cashbox: 116, cassette: 280, cassetteGraph: 80, editWidth: 174 },
  3: { cashbox: 106, cassette: 200, cassetteGraph: 60, editWidth: 145 },
  4: { cashbox: 106, cassette: 164, cassetteGraph: 40, editWidth: 90 }
}

const ValidationSchema = Yup.object().shape({
  name: Yup.string().required('Required'),
  cashbox: Yup.number()
    .label('Cashbox')
    .required()
    .integer()
    .min(0)
    .max(1000),
  cassette1: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500),
  cassette2: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500),
  cassette3: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500),
  cassette4: Yup.number()
    .required('Required')
    .integer()
    .min(0)
    .max(500)
})

const SET_CASSETTE_BILLS = gql`
  mutation MachineAction(
    $deviceId: ID!
    $action: MachineAction!
    $cashbox: Int!
    $cassette1: Int!
    $cassette2: Int!
    $cassette3: Int!
    $cassette4: Int!
  ) {
    machineAction(
      deviceId: $deviceId
      action: $action
      cashbox: $cashbox
      cassette1: $cassette1
      cassette2: $cassette2
      cassette3: $cassette3
      cassette4: $cassette4
    ) {
      deviceId
      cashbox
      cassette1
      cassette2
      cassette3
      cassette4
    }
  }
`

const CashCassettes = ({ machine, config, refetchData }) => {
  const data = { machine, config }
  const classes = useStyles()

  const cashout = data?.config && fromNamespace('cashOut')(data.config)
  const locale = data?.config && fromNamespace('locale')(data.config)
  const fiatCurrency = locale?.fiatCurrency
  const numberOfCassettes = machine.numberOfCassettes

  const getCashoutSettings = deviceId => fromNamespace(deviceId)(cashout)
  const isCashOutDisabled = ({ deviceId }) =>
    !getCashoutSettings(deviceId).active

  const elements = [
    {
      name: 'cashbox',
      header: 'Cashbox',
      width: widthsByNumberOfCassettes[numberOfCassettes].cashbox,
      stripe: false,
      view: value => (
        <CashIn currency={{ code: fiatCurrency }} notes={value} total={0} />
      ),
      input: NumberInput,
      inputProps: {
        decimalPlaces: 0
      }
    }
  ]

  R.until(
    R.gt(R.__, numberOfCassettes),
    it => {
      elements.push({
        name: `cassette${it}`,
        header: `Cash-out ${it}`,
        width: widthsByNumberOfCassettes[numberOfCassettes].cassette,
        stripe: true,
        doubleHeader: 'Cash-out',
        view: value => {
          return (
            <CashOut
              className={classes.cashbox}
              denomination={
                getCashoutSettings(machine.deviceId)?.[`cassette${it}`]
              }
              currency={{ code: fiatCurrency }}
              notes={value}
              width={widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph}
            />
          )
        },
        isHidden: ({ numberOfCassettes }) => it > numberOfCassettes,
        input: CashCassetteInput,
        inputProps: {
          decimalPlaces: 0,
          width: widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph,
          inputClassName: classes.cashbox
        }
      })
      return R.add(1, it)
    },
    1
  )

  const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
    refetchQueries: () => refetchData()
  })

  const onSave = (
    ...[, { deviceId, cashbox, cassette1, cassette2, cassette3, cassette4 }]
  ) => {
    return setCassetteBills({
      variables: {
        action: 'setCassetteBills',
        deviceId: deviceId,
        cashbox,
        cassette1,
        cassette2,
        cassette3,
        cassette4
      }
    })
  }

  return machine.name ? (
    <EditableTable
      error={error?.message}
      enableEdit
      editWidth={widthsByNumberOfCassettes[numberOfCassettes].editWidth}
      stripeWhen={isCashOutDisabled}
      disableRowEdit={isCashOutDisabled}
      name="cashboxes"
      elements={elements}
      data={[machine]}
      save={onSave}
      validationSchema={ValidationSchema}
    />
  ) : null
}

export default CashCassettes
<|endoftext|>


<commit_before>/**
 * `AuthenticationError` error.
 *
 * @api private
 */
function AuthenticationError(message, status) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'AuthenticationError';
  this.message = message;
  this.status = status || 401;
}

/**
 * Inherit from `Error`.
 */
AuthenticationError.prototype.__proto__ = Error.prototype;

/**
 * Expose `AuthenticationError`.
 */
module.exports = AuthenticationError;
<commit_msg>Simplify JSDoc of AuthenticationError.<commit_after>/**
 * `AuthenticationError` error.
 *
 * @constructor
 * @api private
 */
function AuthenticationError(message, status) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'AuthenticationError';
  this.message = message;
  this.status = status || 401;
}

// Inherit from `Error`.
AuthenticationError.prototype.__proto__ = Error.prototype;

// Expose constructor.
module.exports = AuthenticationError;
<|endoftext|>


<commit_before>'use strict';

/**
 * A service that offers the current selection in a table.
 * Offers the api to control the selection, too.
 *
 * @class
 *
 * @param {EventBus} eventBus the event bus
 */
function Selection(eventBus) {

  this._eventBus = eventBus;

  this._selectedElement = null;
}

Selection.$inject = [ 'eventBus' ];

module.exports = Selection;

Selection.prototype.deselect = function(skipEvent) {
  if (this._selectedElement) {
    var oldSelection = this._selectedElement;

    this._selectedElement.row.selected = false;
    this._selectedElement.column.selected = false;
    this._selectedElement.selected = false;
    this._selectedElement = null;
    if(!skipEvent) {
      this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: this._selectedElement });
    }
    return oldSelection;
  }
};

Selection.prototype.get = function() {
  return this._selectedElement;
};

Selection.prototype.isSelected = function(element) {
  return this._selectedElement === element;
};

/**
 * This method selects a cell in the table.
 *
 * @method Selection#select
 *
 * @param  {Object} element element to be selected
 */
Selection.prototype.select = function(element) {
  if(this.isSelected(element)) {
    return;
  }

  var oldSelection = this._selectedElement;

  if(oldSelection) {
    this.deselect(true);
  }

  this._selectedElement = element;
  element.selected = true;
  element.row.selected = true;
  element.column.selected = true;

  this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: this._selectedElement });
};
<commit_msg>fix(selection): do not try to select invalid element<commit_after>'use strict';

/**
 * A service that offers the current selection in a table.
 * Offers the api to control the selection, too.
 *
 * @class
 *
 * @param {EventBus} eventBus the event bus
 */
function Selection(eventBus) {

  this._eventBus = eventBus;

  this._selectedElement = null;
}

Selection.$inject = [ 'eventBus' ];

module.exports = Selection;

Selection.prototype.deselect = function(skipEvent) {
  if (this._selectedElement) {
    var oldSelection = this._selectedElement;

    this._selectedElement.row.selected = false;
    this._selectedElement.column.selected = false;
    this._selectedElement.selected = false;
    this._selectedElement = null;
    if(!skipEvent) {
      this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: this._selectedElement });
    }
    return oldSelection;
  }
};

Selection.prototype.get = function() {
  return this._selectedElement;
};

Selection.prototype.isSelected = function(element) {
  return this._selectedElement === element;
};

/**
 * This method selects a cell in the table.
 *
 * @method Selection#select
 *
 * @param  {Object} element element to be selected
 */
Selection.prototype.select = function(element) {
  if(!element || this.isSelected(element)) {
    return;
  }

  var oldSelection = this._selectedElement;

  if(oldSelection) {
    this.deselect(true);
  }

  this._selectedElement = element;
  element.selected = true;
  element.row.selected = true;
  element.column.selected = true;

  this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: this._selectedElement });
};
<|endoftext|>