<commit_before>var expect = require('chai').expect;
var axios = require('axios');

describe('Server tests', function() {

  describe('/', function() {
    it('should return index.html on a get request', function(done) {
      axios.get('http://localhost:8080/')
        .then(function (response) {
          expect(response.data).to.contain('ng-app');
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });
  });

  describe('/login', function() {
    it('should return a response on a post request', function(done) {
      axios.post('http://localhost:8080/login')
        .then(function (response) {
          expect(response.data).to.exist;
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });
  });

  describe('/signup', function() {
    it('should return a response on a post request', function(done) {
      axios.post('http://localhost:8080/signup')
        .then(function (response) {
          expect(response.data).to.exist;
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });

    it('should return a json web token', function(done) {
      axios.post('http://localhost:8080/signup')
        .then(function (response) {
          expect(response.data.token).to.exist;
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });
  });

});<commit_msg>Add web token test to login<commit_after>var expect = require('chai').expect;
var axios = require('axios');

describe('Server tests', function() {

  describe('/', function() {
    it('should return index.html on a get request', function(done) {
      axios.get('http://localhost:8080/')
        .then(function (response) {
          expect(response.data).to.contain('ng-app');
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });
  });

  describe('/login', function() {
    it('should return a response on a post request', function(done) {
      axios.post('http://localhost:8080/login')
        .then(function (response) {
          expect(response.data).to.exist;
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });

    it('should return a json web token', function(done) {
      axios.post('http://localhost:8080/signup')
        .then(function (response) {
          expect(response.data.token).to.exist;
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });
  });

  describe('/signup', function() {
    it('should return a response on a post request', function(done) {
      axios.post('http://localhost:8080/signup')
        .then(function (response) {
          expect(response.data).to.exist;
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });

    it('should return a json web token', function(done) {
      axios.post('http://localhost:8080/signup')
        .then(function (response) {
          expect(response.data.token).to.exist;
          done();
        })
        .catch(function (error) {
          console.log(error);
          done();
        });
    });
  });

});<|endoftext|>


<commit_before>import mq from '../../utils/media-query'
import PropTypes from 'prop-types'
import React, { Component, Children } from 'react'
import styled from 'styled-components'
// lodash
import get from 'lodash/get'
import map from 'lodash/map'

const _ = {
  get,
  map
}

const SlidesContainer = styled.div`
  position: relative;
  overflow: visible;
  touch-action: pan-y;
  ${mq.mobileOnly`
    height: 300px;
    height: calc(100vh - 258px);
  `}
  ${mq.tabletOnly`
    height: calc(100vh - 258px);
  `}
  ${mq.desktopAndAbove`
    height: calc(100vh - 200px);
  `}
`

const Slides = styled.ul`
  position: absolute;
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: nowrap;
  transition-property: ${props => props.isSliding ? 'transform' : 'none'};
  transform: ${props => props.offset !== 0 ? `translateX(calc(${props.offset * 1}px - ${props.currentSlide * 100}vw))` : `translateX(-${props.currentSlide * 100}vw)`};
  transition-duration: ${props => props.transitionDuration};
  transition-timing-function: ${props => props.transitionTimingFunction};
  will-change: transform;
  height: 100%;
`

const Slide = styled.li`
  flex: 0 0 100vw;
  height: 100%;
`

const Indicators = styled.ol`
  padding: 0;
  list-style-type: none;
	text-align: center;
  width: 100%;
  margin: 80px auto 100px auto;
  ${mq.tabletAndAbove`
    margin: 30px auto 60px auto;
  `}
`

const Indicator = styled.li`
	display: inline-block;
	min-width: 10px;
	min-height: 10px;
	width: .6em;
	height: .6em;
  background-color: ${props => props.focus ? 'white' : '#BEC0BC' };
	margin: 0 .8em;
	border-radius: 50%;
	overflow: hidden;
	cursor: pointer;
  text-indent: 100%;
`

const Button = styled.div`
  background-color: transparent;
  border: 0;
  cursor: pointer;
  height: 43px;
  opacity: .75;
  outline: none;
  padding: 0;
  position: absolute;
  background-repeat: no-repeat;
  background-size: contain;
  margin: 0 1em;
  top: 50%;
  transform: translateY(-50%);
  width: 43px;
  ${mq.mobileOnly`
    display: none;
  `}
`

const PrevBtn = styled(Button)`
  left: 0;
  background-image: url('/asset/photography/topnews-prev.svg');
`

const NextBtn = styled(Button)`
  right: 0;
  background-image: url('/asset/photography/topnews-next.svg');
`

class Carousel extends Component {
  constructor(props) {
    super(props)
    this.state = {
      currentSlide: this.props.initialSlide,
      dragPosition: null,
      isSliding: false,
      offset: 0
    }
    this.setTimer = this.setTimer.bind(this)
    this.clearTimer = this.clearTimer.bind(this)
    this.events = {
      onTouchStart: this.onDraggingStart.bind(this),
      onTouchMove: this.onDraggingMove.bind(this),
      onTouchEnd: this.onDraggingEnd.bind(this),
      onTouchCancel: this.onDraggingEnd.bind(this),
      onClick: this.onClick.bind(this),
      onTransitionEnd: this.onTransitionEnd.bind(this)
    }
  }

  componentDidMount() {
    this.setTimer()
  }

  componentWillUnmount() {
    this.clearTimer()
  }

  onTransitionEnd() { // this will not be triggered when document.hidden
    const { currentSlide } = this.state
    let fixedSlide = currentSlide
    const count = Children.count(this.props.children)
    if (currentSlide == count + 1) fixedSlide = 1
    if (currentSlide == 0) fixedSlide = count
    this.setState({ currentSlide: fixedSlide, isSliding: false }, () => {
      this.setTimer()
      this.props.slideDidChange && this.props.slideDidChange(fixedSlide)
    })
  }

  setTimer() {
    const interval = this.props.autoPlayInterval
    if (Children.count(this.props.children) > 1 && interval > 0) {
      this.clearTimer()
      this.timer = window.setInterval(this.changeSlide.bind(this, this.state.currentSlide + 1), interval)
    }
  }

  clearTimer() {
    window.clearInterval(this.timer)
  }

  changeSlide(targetSlide) {
    if (document.hidden) return // run only when page is visible
    if (this.props.slideWillChange && !this.props.slideWillChange(targetSlide, this.state.currentSlide)) return
    if (targetSlide >= 0 && targetSlide <= React.Children.count(this.props.children) + 1)
      this.setState({ currentSlide: targetSlide, isSliding: true, dragPosition: null, offset: 0 }, this.setTimer)
  }

  onDraggingStart(event) {
    if (event.touches)
      this.setState({ dragPosition: {
        x: event.touches[0].pageX,
        y: event.touches[0].pageY
      }, offset: 0 })
  }

  onDraggingMove(event) {
    const { isSliding, dragPosition } = this.state
    if (isSliding || !dragPosition || !event.touches) return
    const x = event.touches[0].pageX
    const y = event.touches[0].pageY
    const offset = x - dragPosition.x
    if (Math.abs(y - dragPosition.y) < Math.abs(offset)) event.preventDefault()
    this.setState({ offset })
  }

  onDraggingEnd(event) {
    const sliderWidth = event.currentTarget.clientWidth
    const { currentSlide, offset, dragPosition } = this.state
    if (!dragPosition) return
    const target = Math.abs(offset) > sliderWidth / 5 ? (offset > 0 ? currentSlide - 1 : currentSlide + 1) : currentSlide
    this.setState({ dragPosition: null }, this.changeSlide.bind(this, target))
  }

  onClick(event) {
    if (Math.abs(this.state.offset) < 25) return // trigger click in a small distance
    event.preventDefault()
    event.stopPropagation()
    event.nativeEvent.stopPropagation()
  }

  _renderSlides() {
    const children = React.Children.toArray(this.props.children)
    const { currentSlide } = this.state
    return _.map([
      React.cloneElement(children[children.length - 1], { key: `${children[children.length - 1].key}-clone` }),
      ...children,
      React.cloneElement(children[0], { key: `${children[0].key}-clone` })
    ], (item, index) => {
      return <Slide key={`slide-${item.key}`} focus={currentSlide === index} >{item}</Slide>
    })
  }

  _renderIndicators() {
    return Children.map(this.props.children, (item, index) =>
      <Indicator
        key={`i-${index + 1}`}
        focus={this.state.currentSlide === index + 1}
        onClick={this.changeSlide.bind(this, index + 1)}
      >
        {index + 1}
      </Indicator>
    )
  }

  render() {
    const {
      className,
      transitionDuration,
      transitionTimingFunction
    } = this.props
    const { currentSlide, isSliding, offset } = this.state
    const goPrevSlide = this.changeSlide.bind(this, currentSlide - 1)
    const goNextSlide = this.changeSlide.bind(this, currentSlide + 1)

    return (

        <SlidesContainer>
          <Slides
            currentSlide={currentSlide}
            isSliding={isSliding}
            offset={offset}
            transitionDuration={transitionDuration}
            transitionTimingFunction={transitionTimingFunction}
            {...this.events}
          >
            {this._renderSlides()}
          </Slides>
          <PrevBtn type="button" className="prev" onClick={goPrevSlide}></PrevBtn>
          <NextBtn type="button" className="next" onClick={goNextSlide}></NextBtn>
        </SlidesContainer>
        <Indicators>
          {this._renderIndicators()}
        </Indicators>

    )
  }
}

Carousel.propTypes = {
  autoPlayInterval: PropTypes.number,
  children: PropTypes.node,
  className: PropTypes.string,
  initialSlide: PropTypes.number,
  slideDidChange: PropTypes.func,
  slideWillChange: PropTypes.func,
  transitionDuration: PropTypes.string,
  transitionTimingFunction: PropTypes.string
}

Carousel.defaultProps = {
  autoPlayInterval: 0,
  initialSlide: 1, // slide index start from 1
  transitionDuration: '.8s',
  transitionTimingFunction: 'ease-in-out'
}

export default Carousel
<commit_msg>Remove `type=“button”`<commit_after>import mq from '../../utils/media-query'
import PropTypes from 'prop-types'
import React, { Component, Children } from 'react'
import styled from 'styled-components'
// lodash
import get from 'lodash/get'
import map from 'lodash/map'

const _ = {
  get,
  map
}

const SlidesContainer = styled.div`
  position: relative;
  overflow: visible;
  touch-action: pan-y;
  ${mq.mobileOnly`
    height: 300px;
    height: calc(100vh - 258px);
  `}
  ${mq.tabletOnly`
    height: calc(100vh - 258px);
  `}
  ${mq.desktopAndAbove`
    height: calc(100vh - 200px);
  `}
`

const Slides = styled.ul`
  position: absolute;
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: nowrap;
  transition-property: ${props => props.isSliding ? 'transform' : 'none'};
  transform: ${props => props.offset !== 0 ? `translateX(calc(${props.offset * 1}px - ${props.currentSlide * 100}vw))` : `translateX(-${props.currentSlide * 100}vw)`};
  transition-duration: ${props => props.transitionDuration};
  transition-timing-function: ${props => props.transitionTimingFunction};
  will-change: transform;
  height: 100%;
`

const Slide = styled.li`
  flex: 0 0 100vw;
  height: 100%;
`

const Indicators = styled.ol`
  padding: 0;
  list-style-type: none;
	text-align: center;
  width: 100%;
  margin: 80px auto 100px auto;
  ${mq.tabletAndAbove`
    margin: 30px auto 60px auto;
  `}
`

const Indicator = styled.li`
	display: inline-block;
	min-width: 10px;
	min-height: 10px;
	width: .6em;
	height: .6em;
  background-color: ${props => props.focus ? 'white' : '#BEC0BC' };
	margin: 0 .8em;
	border-radius: 50%;
	overflow: hidden;
	cursor: pointer;
  text-indent: 100%;
`

const Button = styled.div`
  background-color: transparent;
  border: 0;
  cursor: pointer;
  height: 43px;
  opacity: .75;
  outline: none;
  padding: 0;
  position: absolute;
  background-repeat: no-repeat;
  background-size: contain;
  margin: 0 1em;
  top: 50%;
  transform: translateY(-50%);
  width: 43px;
  ${mq.mobileOnly`
    display: none;
  `}
`

const PrevBtn = styled(Button)`
  left: 0;
  background-image: url('/asset/photography/topnews-prev.svg');
`

const NextBtn = styled(Button)`
  right: 0;
  background-image: url('/asset/photography/topnews-next.svg');
`

class Carousel extends Component {
  constructor(props) {
    super(props)
    this.state = {
      currentSlide: this.props.initialSlide,
      dragPosition: null,
      isSliding: false,
      offset: 0
    }
    this.setTimer = this.setTimer.bind(this)
    this.clearTimer = this.clearTimer.bind(this)
    this.events = {
      onTouchStart: this.onDraggingStart.bind(this),
      onTouchMove: this.onDraggingMove.bind(this),
      onTouchEnd: this.onDraggingEnd.bind(this),
      onTouchCancel: this.onDraggingEnd.bind(this),
      onClick: this.onClick.bind(this),
      onTransitionEnd: this.onTransitionEnd.bind(this)
    }
  }

  componentDidMount() {
    this.setTimer()
  }

  componentWillUnmount() {
    this.clearTimer()
  }

  onTransitionEnd() { // this will not be triggered when document.hidden
    const { currentSlide } = this.state
    let fixedSlide = currentSlide
    const count = Children.count(this.props.children)
    if (currentSlide == count + 1) fixedSlide = 1
    if (currentSlide == 0) fixedSlide = count
    this.setState({ currentSlide: fixedSlide, isSliding: false }, () => {
      this.setTimer()
      this.props.slideDidChange && this.props.slideDidChange(fixedSlide)
    })
  }

  setTimer() {
    const interval = this.props.autoPlayInterval
    if (Children.count(this.props.children) > 1 && interval > 0) {
      this.clearTimer()
      this.timer = window.setInterval(this.changeSlide.bind(this, this.state.currentSlide + 1), interval)
    }
  }

  clearTimer() {
    window.clearInterval(this.timer)
  }

  changeSlide(targetSlide) {
    if (document.hidden) return // run only when page is visible
    if (this.props.slideWillChange && !this.props.slideWillChange(targetSlide, this.state.currentSlide)) return
    if (targetSlide >= 0 && targetSlide <= React.Children.count(this.props.children) + 1)
      this.setState({ currentSlide: targetSlide, isSliding: true, dragPosition: null, offset: 0 }, this.setTimer)
  }

  onDraggingStart(event) {
    if (event.touches)
      this.setState({ dragPosition: {
        x: event.touches[0].pageX,
        y: event.touches[0].pageY
      }, offset: 0 })
  }

  onDraggingMove(event) {
    const { isSliding, dragPosition } = this.state
    if (isSliding || !dragPosition || !event.touches) return
    const x = event.touches[0].pageX
    const y = event.touches[0].pageY
    const offset = x - dragPosition.x
    if (Math.abs(y - dragPosition.y) < Math.abs(offset)) event.preventDefault()
    this.setState({ offset })
  }

  onDraggingEnd(event) {
    const sliderWidth = event.currentTarget.clientWidth
    const { currentSlide, offset, dragPosition } = this.state
    if (!dragPosition) return
    const target = Math.abs(offset) > sliderWidth / 5 ? (offset > 0 ? currentSlide - 1 : currentSlide + 1) : currentSlide
    this.setState({ dragPosition: null }, this.changeSlide.bind(this, target))
  }

  onClick(event) {
    if (Math.abs(this.state.offset) < 25) return // trigger click in a small distance
    event.preventDefault()
    event.stopPropagation()
    event.nativeEvent.stopPropagation()
  }

  _renderSlides() {
    const children = React.Children.toArray(this.props.children)
    const { currentSlide } = this.state
    return _.map([
      React.cloneElement(children[children.length - 1], { key: `${children[children.length - 1].key}-clone` }),
      ...children,
      React.cloneElement(children[0], { key: `${children[0].key}-clone` })
    ], (item, index) => {
      return <Slide key={`slide-${item.key}`} focus={currentSlide === index} >{item}</Slide>
    })
  }

  _renderIndicators() {
    return Children.map(this.props.children, (item, index) =>
      <Indicator
        key={`i-${index + 1}`}
        focus={this.state.currentSlide === index + 1}
        onClick={this.changeSlide.bind(this, index + 1)}
      >
        {index + 1}
      </Indicator>
    )
  }

  render() {
    const {
      className,
      transitionDuration,
      transitionTimingFunction
    } = this.props
    const { currentSlide, isSliding, offset } = this.state
    const goPrevSlide = this.changeSlide.bind(this, currentSlide - 1)
    const goNextSlide = this.changeSlide.bind(this, currentSlide + 1)

    return (

        <SlidesContainer>
          <Slides
            currentSlide={currentSlide}
            isSliding={isSliding}
            offset={offset}
            transitionDuration={transitionDuration}
            transitionTimingFunction={transitionTimingFunction}
            {...this.events}
          >
            {this._renderSlides()}
          </Slides>
          <PrevBtn className="prev" onClick={goPrevSlide}></PrevBtn>
          <NextBtn className="next" onClick={goNextSlide}></NextBtn>
        </SlidesContainer>
        <Indicators>
          {this._renderIndicators()}
        </Indicators>

    )
  }
}

Carousel.propTypes = {
  autoPlayInterval: PropTypes.number,
  children: PropTypes.node,
  className: PropTypes.string,
  initialSlide: PropTypes.number,
  slideDidChange: PropTypes.func,
  slideWillChange: PropTypes.func,
  transitionDuration: PropTypes.string,
  transitionTimingFunction: PropTypes.string
}

Carousel.defaultProps = {
  autoPlayInterval: 0,
  initialSlide: 1, // slide index start from 1
  transitionDuration: '.8s',
  transitionTimingFunction: 'ease-in-out'
}

export default Carousel
<|endoftext|>


<commit_before>import assert from 'power-assert';
import cloneDeep from 'lodash/cloneDeep';
import Harness from '../../../test/harness';
import SelectComponent from './Select';
import { expect } from 'chai';
import NativePromise from 'native-promise-only';

import {
  comp1,
  comp2,
  multiSelect,
  multiSelectOptions,
  comp4,
  comp5,
  comp6
} from './fixtures';

describe('Select Component', () => {
  it('should not stringify select option value', function(done) {
    Harness.testCreate(SelectComponent, comp6).then((component) => {
      component.setValue({ value:'a', label:'A' });

      assert.equal(component.choices._currentState.items[0].value.value, 'a');
      assert.equal(typeof component.choices._currentState.items[0].value , 'object');
      assert.equal(component.dataValue.value, 'a');
      assert.equal(typeof component.dataValue , 'object');
      done();
    });
  });

  it('should return string value for different value types', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const stringValue = component.asString(true);
      const stringValue1 = component.asString(11);
      const stringValue2 = component.asString('test');
      const stringValue3 = component.asString(12);
      assert.equal(stringValue, 'true');
      assert.equal(stringValue1, '11');
      assert.equal(stringValue2, 'test');
      assert.equal(stringValue3, '1.2');
      done();
    });
  });

  it('should correctly determine storage type when dataType is auto', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue('true');
      const value1 = component.normalizeSingleValue('11');
      const value2 = component.normalizeSingleValue('test');
      const value3 = component.normalizeSingleValue('11test11test');
      const value4 = component.normalizeSingleValue('test11');
      const value5 = component.normalizeSingleValue('0');
      const value6 = component.normalizeSingleValue('');
      assert.equal(typeof value, 'boolean');
      assert.equal(typeof value1, 'number');
      assert.equal(typeof value2, 'string');
      assert.equal(typeof value3, 'string');
      assert.equal(typeof value4, 'string');
      assert.equal(typeof value5, 'number');
      assert.equal(typeof value6, 'string');
      done();
    });
  });

  it('should not stringify default empty values', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue({});
      const value1 = component.normalizeSingleValue([]);
      assert.equal(typeof value, 'object');
      assert.equal(typeof value1, 'object');
      done();
    });
  });

  it('should not change value letter case', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue('data.textArea');
      const value1 = component.normalizeSingleValue('ECMAScript');
      const value2 = component.normalizeSingleValue('JS');
      assert.equal(value, 'data.textArea');
      assert.equal(value1, 'ECMAScript');
      assert.equal(value2, 'JS');
      done();
    });
  });

  it('should define boolean value', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue('TRUE');
      const value1 = component.normalizeSingleValue('False');
      const value2 = component.normalizeSingleValue('true');
      assert.equal(value, true);
      assert.equal(value1, false);
      assert.equal(value2, true);
      done();
    });
  });

  it('1/2 should not display empty choice options if property value is not defined', function(done) {
    Harness.testCreate(SelectComponent, comp5).then((component) => {
      component.setItems([{
        'label': '111',
        'value': '111'
      }, {
        'label': '222',
        'value': '222'
      }, {
        'label': '333',
        'value': '333'
      }], false);
      assert.equal(component.selectOptions.length, 0);
      done();
    });
  });

  it('2/2 should display choice option if property value is set', function(done) {
    comp5.template = '{{ item.label }}';
    Harness.testCreate(SelectComponent, comp5).then((component) => {
      component.setItems([{
        'label': '111',
        'value': '111'
      }, {
        'label': '222',
        'value': '222'
      }, {
        'label': '333',
        'value': '333'
      }], false);
      assert.equal(component.selectOptions.length, 3);
      done();
    });
  });

  it('should have only unique dropdown options', function(done) {
    comp5.template = '{{ item.label }}';
    comp5.uniqueOptions = true;
    Harness.testCreate(SelectComponent, comp5).then((component) => {
      component.setItems([{
        'label': 'Label 1',
        'value': 'value1'
      }, {
        'label': 'Label 2',
        'value': 'value2'
      }, {
        'label': 'Label 3',
        'value': 'value3'
      }, {
        'label': 'Label 4',
        'value': 'value3'
      }], false);

      assert.equal(component.selectOptions.length, 3);
      done();
    });
  });

  it('should set multiple selected values not repeating them', function(done) {
    Harness.testCreate(SelectComponent, multiSelect).then((component) => {
      component.setItems(multiSelectOptions, false);
      component.setChoicesValue(['Cheers']);
      component.setChoicesValue(['Cheers', 'Cyberdyne Systems'], 1);
      component.setChoicesValue(['Cheers', 'Cyberdyne Systems', 'Massive Dynamic'], 2);
      const choices = component.element.querySelector('.choices__list--multiple').children;
      assert.equal(choices.length, 3);
      done();
    });
  });

  it('should not show selected values in dropdown when searching', function(done) {
    Harness.testCreate(SelectComponent, multiSelect).then((component) => {
      component.setItems(multiSelectOptions, false);
      component.setChoicesValue(['Cheers']);
      component.setChoicesValue(['Cheers', 'Cyberdyne Systems'], 1);
      component.setItems([], true);
      const itemsInDropdown = component.element.querySelectorAll('.choices__item--choice');
      const choices = component.element.querySelector('.choices__list--multiple').children;
      assert.equal(choices.length, 2);
      assert.equal(itemsInDropdown.length, 1);
      done();
    });
  });

  it('Should build a Select component', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      Harness.testElements(component, 'select', 1);
    });
  });

  it('Should preserve the tabindex', () => {
    return Harness.testCreate(SelectComponent, comp2).then((component) => {
      const element = component.element.getElementsByClassName('choices__list choices__list--single')[0];
      Harness.testElementAttribute(element, 'tabindex', '10');
    });
  });

  it('Should default to 0 when tabindex is not specified', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      const element = component.element.getElementsByClassName('choices__list choices__list--single')[0];
      Harness.testElementAttribute(element, 'tabindex', '0');
    });
  });

  it('Should allow to override threshold option of fuzzy search', () => {
    try {
      const c1 = Object.assign(cloneDeep(comp1), { searchThreshold: 0.2 });
      const c2 = Object.assign(cloneDeep(comp1), { searchThreshold: 0.4 });
      const c3 = Object.assign(cloneDeep(comp1), { searchThreshold: 0.8 });
      const comps = [
        Harness.testCreate(SelectComponent, c1),
        Harness.testCreate(SelectComponent, c2),
        Harness.testCreate(SelectComponent, c3),
      ];

      return NativePromise
        .all(comps)
        .then(([a, b, c]) => {
          expect(a.choices.config.fuseOptions.threshold).to.equal(0.2);
          expect(b.choices.config.fuseOptions.threshold).to.equal(0.4);
          expect(c.choices.config.fuseOptions.threshold).to.equal(0.8);
        });
    }
    catch (error) {
      return NativePromise.reject(error);
    }
  });

  it('should set component value', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      assert.deepEqual(component.dataValue, '');
      component.setValue('red');
      assert.equal(component.dataValue, 'red');
    });
  });

  it('should remove selected item', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      assert.deepEqual(component.dataValue, '');
      component.setValue('red');
      assert.equal(component.dataValue, 'red');

      const element = component.element.getElementsByClassName('choices__button')[0];
      component.choices._handleButtonAction(component.choices._store.activeItems, element);

      assert.equal(component.dataValue, '');
    });
  });

  it('should open dropdown after item has been removed', () => {
    global.requestAnimationFrame = cb => cb();
    window.matchMedia = window.matchMedia || function() {
      return {
        matches : false,
        addListener : function() {},
        removeListener: function() {}
      };
    };

    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      component.setValue('red');

      const element = component.element.getElementsByClassName('choices__button')[0];
      component.choices._handleButtonAction(component.choices._store.activeItems, element);

      component.choices.showDropdown(true);

      assert.equal(component.choices.dropdown.isActive, true);
    });
  });

  it('should keep dropdown closed after item has been removed by keypress', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      component.setValue('red');

      const element = component.element.querySelector('.choices__button');
      const ke = new KeyboardEvent('keydown', {
        bubbles: true, cancelable: true, keyCode: 13
      });

      element.dispatchEvent(ke);

      assert.equal(component.dataValue, '');
      assert.equal(component.choices.dropdown.isActive, false);
    });
  });

  // it('should reset input value when called with empty value', () => {
  //   const comp = Object.assign({}, comp1);
  //   delete comp.placeholder;
  //
  //   return Harness.testCreate(SelectComponent, comp).then((component) => {
  //     assert.deepEqual(component.dataValue, '');
  //     assert.equal(component.refs.input[0].value, '');
  //     component.setValue('red');
  //     assert.equal(component.dataValue, 'red');
  //     assert.equal(component.refs.input[0].value, 'red');
  //     component.setValue('');
  //     assert.equal(component.dataValue, '');
  //     assert.equal(component.refs.input[0].value, '');
  //   });
  // });
});
<commit_msg>fixed test<commit_after>import assert from 'power-assert';
import cloneDeep from 'lodash/cloneDeep';
import Harness from '../../../test/harness';
import SelectComponent from './Select';
import { expect } from 'chai';
import NativePromise from 'native-promise-only';

import {
  comp1,
  comp2,
  multiSelect,
  multiSelectOptions,
  comp4,
  comp5,
  comp6
} from './fixtures';

describe('Select Component', () => {
  it('should not stringify select option value', function(done) {
    Harness.testCreate(SelectComponent, comp6).then((component) => {
      component.setValue({ value:'a', label:'A' });
      setTimeout(()=> {
        assert.equal(component.choices._currentState.items[0].value.value, 'a');
        assert.equal(typeof component.choices._currentState.items[0].value , 'object');
        assert.equal(component.dataValue.value, 'a');
        assert.equal(typeof component.dataValue , 'object');
        done();
      }, 100);
    });
  });

  it('should return string value for different value types', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const stringValue = component.asString(true);
      const stringValue1 = component.asString(11);
      const stringValue2 = component.asString('test');
      const stringValue3 = component.asString(12);
      assert.equal(stringValue, 'true');
      assert.equal(stringValue1, '11');
      assert.equal(stringValue2, 'test');
      assert.equal(stringValue3, '1.2');
      done();
    });
  });

  it('should correctly determine storage type when dataType is auto', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue('true');
      const value1 = component.normalizeSingleValue('11');
      const value2 = component.normalizeSingleValue('test');
      const value3 = component.normalizeSingleValue('11test11test');
      const value4 = component.normalizeSingleValue('test11');
      const value5 = component.normalizeSingleValue('0');
      const value6 = component.normalizeSingleValue('');
      assert.equal(typeof value, 'boolean');
      assert.equal(typeof value1, 'number');
      assert.equal(typeof value2, 'string');
      assert.equal(typeof value3, 'string');
      assert.equal(typeof value4, 'string');
      assert.equal(typeof value5, 'number');
      assert.equal(typeof value6, 'string');
      done();
    });
  });

  it('should not stringify default empty values', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue({});
      const value1 = component.normalizeSingleValue([]);
      assert.equal(typeof value, 'object');
      assert.equal(typeof value1, 'object');
      done();
    });
  });

  it('should not change value letter case', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue('data.textArea');
      const value1 = component.normalizeSingleValue('ECMAScript');
      const value2 = component.normalizeSingleValue('JS');
      assert.equal(value, 'data.textArea');
      assert.equal(value1, 'ECMAScript');
      assert.equal(value2, 'JS');
      done();
    });
  });

  it('should define boolean value', function(done) {
    Harness.testCreate(SelectComponent, comp4).then((component) => {
      const value = component.normalizeSingleValue('TRUE');
      const value1 = component.normalizeSingleValue('False');
      const value2 = component.normalizeSingleValue('true');
      assert.equal(value, true);
      assert.equal(value1, false);
      assert.equal(value2, true);
      done();
    });
  });

  it('1/2 should not display empty choice options if property value is not defined', function(done) {
    Harness.testCreate(SelectComponent, comp5).then((component) => {
      component.setItems([{
        'label': '111',
        'value': '111'
      }, {
        'label': '222',
        'value': '222'
      }, {
        'label': '333',
        'value': '333'
      }], false);
      assert.equal(component.selectOptions.length, 0);
      done();
    });
  });

  it('2/2 should display choice option if property value is set', function(done) {
    comp5.template = '{{ item.label }}';
    Harness.testCreate(SelectComponent, comp5).then((component) => {
      component.setItems([{
        'label': '111',
        'value': '111'
      }, {
        'label': '222',
        'value': '222'
      }, {
        'label': '333',
        'value': '333'
      }], false);
      assert.equal(component.selectOptions.length, 3);
      done();
    });
  });

  it('should have only unique dropdown options', function(done) {
    comp5.template = '{{ item.label }}';
    comp5.uniqueOptions = true;
    Harness.testCreate(SelectComponent, comp5).then((component) => {
      component.setItems([{
        'label': 'Label 1',
        'value': 'value1'
      }, {
        'label': 'Label 2',
        'value': 'value2'
      }, {
        'label': 'Label 3',
        'value': 'value3'
      }, {
        'label': 'Label 4',
        'value': 'value3'
      }], false);

      assert.equal(component.selectOptions.length, 3);
      done();
    });
  });

  it('should set multiple selected values not repeating them', function(done) {
    Harness.testCreate(SelectComponent, multiSelect).then((component) => {
      component.setItems(multiSelectOptions, false);
      component.setChoicesValue(['Cheers']);
      component.setChoicesValue(['Cheers', 'Cyberdyne Systems'], 1);
      component.setChoicesValue(['Cheers', 'Cyberdyne Systems', 'Massive Dynamic'], 2);
      const choices = component.element.querySelector('.choices__list--multiple').children;
      assert.equal(choices.length, 3);
      done();
    });
  });

  it('should not show selected values in dropdown when searching', function(done) {
    Harness.testCreate(SelectComponent, multiSelect).then((component) => {
      component.setItems(multiSelectOptions, false);
      component.setChoicesValue(['Cheers']);
      component.setChoicesValue(['Cheers', 'Cyberdyne Systems'], 1);
      component.setItems([], true);
      const itemsInDropdown = component.element.querySelectorAll('.choices__item--choice');
      const choices = component.element.querySelector('.choices__list--multiple').children;
      assert.equal(choices.length, 2);
      assert.equal(itemsInDropdown.length, 1);
      done();
    });
  });

  it('Should build a Select component', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      Harness.testElements(component, 'select', 1);
    });
  });

  it('Should preserve the tabindex', () => {
    return Harness.testCreate(SelectComponent, comp2).then((component) => {
      const element = component.element.getElementsByClassName('choices__list choices__list--single')[0];
      Harness.testElementAttribute(element, 'tabindex', '10');
    });
  });

  it('Should default to 0 when tabindex is not specified', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      const element = component.element.getElementsByClassName('choices__list choices__list--single')[0];
      Harness.testElementAttribute(element, 'tabindex', '0');
    });
  });

  it('Should allow to override threshold option of fuzzy search', () => {
    try {
      const c1 = Object.assign(cloneDeep(comp1), { searchThreshold: 0.2 });
      const c2 = Object.assign(cloneDeep(comp1), { searchThreshold: 0.4 });
      const c3 = Object.assign(cloneDeep(comp1), { searchThreshold: 0.8 });
      const comps = [
        Harness.testCreate(SelectComponent, c1),
        Harness.testCreate(SelectComponent, c2),
        Harness.testCreate(SelectComponent, c3),
      ];

      return NativePromise
        .all(comps)
        .then(([a, b, c]) => {
          expect(a.choices.config.fuseOptions.threshold).to.equal(0.2);
          expect(b.choices.config.fuseOptions.threshold).to.equal(0.4);
          expect(c.choices.config.fuseOptions.threshold).to.equal(0.8);
        });
    }
    catch (error) {
      return NativePromise.reject(error);
    }
  });

  it('should set component value', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      assert.deepEqual(component.dataValue, '');
      component.setValue('red');
      assert.equal(component.dataValue, 'red');
    });
  });

  it('should remove selected item', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      assert.deepEqual(component.dataValue, '');
      component.setValue('red');
      assert.equal(component.dataValue, 'red');

      const element = component.element.getElementsByClassName('choices__button')[0];
      component.choices._handleButtonAction(component.choices._store.activeItems, element);

      assert.equal(component.dataValue, '');
    });
  });

  it('should open dropdown after item has been removed', () => {
    global.requestAnimationFrame = cb => cb();
    window.matchMedia = window.matchMedia || function() {
      return {
        matches : false,
        addListener : function() {},
        removeListener: function() {}
      };
    };

    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      component.setValue('red');

      const element = component.element.getElementsByClassName('choices__button')[0];
      component.choices._handleButtonAction(component.choices._store.activeItems, element);

      component.choices.showDropdown(true);

      assert.equal(component.choices.dropdown.isActive, true);
    });
  });

  it('should keep dropdown closed after item has been removed by keypress', () => {
    return Harness.testCreate(SelectComponent, comp1).then((component) => {
      component.setValue('red');

      const element = component.element.querySelector('.choices__button');
      const ke = new KeyboardEvent('keydown', {
        bubbles: true, cancelable: true, keyCode: 13
      });

      element.dispatchEvent(ke);

      assert.equal(component.dataValue, '');
      assert.equal(component.choices.dropdown.isActive, false);
    });
  });

  // it('should reset input value when called with empty value', () => {
  //   const comp = Object.assign({}, comp1);
  //   delete comp.placeholder;
  //
  //   return Harness.testCreate(SelectComponent, comp).then((component) => {
  //     assert.deepEqual(component.dataValue, '');
  //     assert.equal(component.refs.input[0].value, '');
  //     component.setValue('red');
  //     assert.equal(component.dataValue, 'red');
  //     assert.equal(component.refs.input[0].value, 'red');
  //     component.setValue('');
  //     assert.equal(component.dataValue, '');
  //     assert.equal(component.refs.input[0].value, '');
  //   });
  // });
});
<|endoftext|>


<commit_before>'use strict';

const sessionID = window.location.search.substring(1).split('=').pop();

const DEFAULT_PIC = '../assets/default-pic.png';

(() => {

  document.addEventListener("deviceready", onDeviceReady, false);

  function onDeviceReady() {

    document.getElementById('save').onclick = save;
    document.getElementById('btn-take-pic').onclick = takePicture;
    document.getElementById('btn-upload-pic').onclick = uploadPicture;
    document.getElementById('pic1').onclick = (() => showPopup(1));
    document.getElementById('pic2').onclick = (() => showPopup(2));
    document.getElementById('pic3').onclick = (() => showPopup(3));
    document.getElementById('pic4').onclick = (() => showPopup(4));
    document.getElementById('btn-record-audio').onclick = recordAudio;
    document.getElementById('btn-record-video').onclick = recordVideo;

    let pictures = [];
    let picIndex = 0;
    let selectedPicID;

    getSession(sessionID)
      .then(session => {

        getNote(sessionID)
          .then(note => {

            document.getElementById('session-name').innerHTML = session.title;

            if (note) {
              document.getElementById('note').value = note.text;

              if(note.pictures) {
                for (var index = 0; index < note.pictures.length; index++) {
                    document.getElementById('pic' + (index+1)).src = note.pictures[index];
                    pictures.push(note.pictures[index]);
                    picIndex++;
                }
              }

              if(note.video) {
                let source = document.getElementById('note-source-video');
                let video  = document.getElementById('note-video');

                source.src = note.video.src;
                source.type = note.video.type;

                video.load();
                video.hidden = false;

              }
            }

            for (var index = pictures.length; index < 4; index++) {
              document.getElementById('pic' + (index+1)).src = DEFAULT_PIC;
              pictures.push(DEFAULT_PIC);
            }

          })
          .catch(error => console.error('Error while trying to get notes from session ' + session.title, error))
      })
      .catch(error => console.error('Error while trying to get session with ID ' + sessionID, error))

    function save() {
      let data = {
        text: document.getElementById('note').value,
        pictures: pictures,
      };

      let videoSource = document.getElementById('note-source-video');

      if(videoSource.src != "" && videoSource.type != ""){
        data.video = {
            src: videoSource.src,
            type: videoSource.type
        }
      }

      saveNote(sessionID, data);
    }

    function takePicture() {

      navigator.camera.getPicture(
        (image => {
          if (picIndex < 4 ) {
            document.getElementById('pic'+ (picIndex+1)).src = image;
            pictures[picIndex] = image;
            picIndex++;
          }
          else {
            document.getElementById('pic1').src = image;
            pictures[0] = image;
            picIndex = 1;
          }
          }),
        (error => console.error('Error while trying to take a picture', error)),
        {
          quality: 100,
          sourceType: Camera.PictureSourceType.CAMERA,
          encodingType: Camera.EncodingType.PNG,
          destinationType: Camera.DestinationType.NATIVE_URI
        }
      )

    }

    function uploadPicture() {

      navigator.camera.getPicture(
        (image => {
          if (picIndex  < 4 ) {
            document.getElementById('pic'+ (picIndex+1)).src = image;
            pictures[picIndex] = image;
            picIndex++;
          }
          else {
            document.getElementById('pic1').src = image;
            pictures[0] = image;
            picIndex = 1;
          }
        }),
        (error => console.error('Error while trying to take a picture', error)),
        {
          quality: 100,
          sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
          encodingType: Camera.EncodingType.PNG,
          destinationType: Camera.DestinationType.NATIVE_URI
        }
      )

    }

    function handlePopupAction(index) {
      switch (index) {
        case 1:
          deleteImageFromNote(sessionID, document.getElementById('pic'+selectedPicID).src, DEFAULT_PIC );
          document.getElementById('pic'+selectedPicID).src = DEFAULT_PIC;
          picIndex = selectedPicID - 1;
          break;
        default: window.plugins.actionsheet.hide();
      }
    }

    function showPopup(id) {

      if(document.getElementById('pic'+id).src.indexOf('default-pic.png') < 0) {
        selectedPicID = id;

        var options = {
          androidTheme: window.plugins.actionsheet.ANDROID_THEMES.THEME_DEVICE_DEFAULT_LIGHT,
          title: 'Do you want to delete this picture ?',
          androidEnableCancelButton: true,
          buttonLabels: ['Yes, I do', 'No, please don\'t'],
          position: [20, 40],
          destructiveButtonLast: true
        };

        window.plugins.actionsheet.show(options, handlePopupAction);
      }

    }

    function recordAudio(){

      navigator.device.capture.captureAudio(
        mediaFiles => console.log(mediaFiles),
        //mediaFiles => document.getElementById('note-audio').src = mediaFiles[0].fullPath,
        error => {
          console.log('Error while trying to record audio ', error);
          alert('No default audio recording app is defined on your phone. \n Install one and try again');
        },
        {
          limit: 1,
          duration: 60
        })

    }

    function recordVideo(){

      navigator.device.capture.captureVideo(
        mediaFiles => {

          let source = document.getElementById('note-source-video');
          let video  = document.getElementById('note-video');

          let media = mediaFiles[0];

          source.src = media.fullPath;
          source.type = media.type;

          video.load();
          video.hidden = false;
        },
        //mediaFiles => document.getElementById('note-audio').src = mediaFiles[0].fullPath,
        error => console.error('Error while trying to record video'),
        {
          limit: 1,
          duration: 30
        })

    }

  }

})();

// SHARE
// getSession(sessionID)
// .then(session => {
//   var options = {
//     message: 'Here are my notes from the session [ ' + session.title + ' ] taken at Devfest Nantes 2017 : \n\n'
//            + document.getElementById('note').value,
//     subject: 'Notes [ ' + session.title + ' ]',
//     files: [document.getElementById('picture').src],
//     chooserTitle: 'Pick an app'
//   }
//   window.plugins.socialsharing.shareWithOptions(options);
// })
// .catch(error => console.error('Could not find session with id ' + sessionID, error))<commit_msg>fix bug with image index<commit_after>'use strict';

const sessionID = window.location.search.substring(1).split('=').pop();

const DEFAULT_PIC = '../assets/default-pic.png';

(() => {

  document.addEventListener("deviceready", onDeviceReady, false);

  function onDeviceReady() {

    document.getElementById('save').onclick = save;
    document.getElementById('btn-take-pic').onclick = takePicture;
    document.getElementById('btn-upload-pic').onclick = uploadPicture;
    document.getElementById('pic1').onclick = (() => showPopup(1));
    document.getElementById('pic2').onclick = (() => showPopup(2));
    document.getElementById('pic3').onclick = (() => showPopup(3));
    document.getElementById('pic4').onclick = (() => showPopup(4));
    document.getElementById('btn-record-audio').onclick = recordAudio;
    document.getElementById('btn-record-video').onclick = recordVideo;

    let pictures = [];
    let picIndex = 0;
    let selectedPicID;

    getSession(sessionID)
      .then(session => {

        getNote(sessionID)
          .then(note => {

            document.getElementById('session-name').innerHTML = session.title;

            if (note) {
              document.getElementById('note').value = note.text;

              if(note.pictures) {
                for (var index = 0; index < note.pictures.length; index++) {
                    document.getElementById('pic' + (index+1)).src = note.pictures[index];
                    pictures.push(note.pictures[index]);
                    picIndex++;
                }
              }

              if(note.video) {
                let source = document.getElementById('note-source-video');
                let video  = document.getElementById('note-video');

                source.src = note.video.src;
                source.type = note.video.type;

                video.load();
                video.hidden = false;

              }
            }

            for (var index = pictures.length; index < 4; index++) {
              document.getElementById('pic' + (index+1)).src = DEFAULT_PIC;
              pictures.push(DEFAULT_PIC);
            }

          })
          .catch(error => console.error('Error while trying to get notes from session ' + session.title, error))
      })
      .catch(error => console.error('Error while trying to get session with ID ' + sessionID, error))

    function save() {
      let data = {
        text: document.getElementById('note').value,
        pictures: pictures,
      };

      let videoSource = document.getElementById('note-source-video');

      if(videoSource.src != "" && videoSource.type != ""){
        data.video = {
            src: videoSource.src,
            type: videoSource.type
        }
      }

      saveNote(sessionID, data);
    }

    function takePicture() {

      navigator.camera.getPicture(
        (image => {
          if (picIndex < 4 ) {
            document.getElementById('pic'+ (picIndex+1)).src = image;
            pictures[picIndex] = image;
            picIndex++;
          }
          else {
            document.getElementById('pic1').src = image;
            pictures[0] = image;
            picIndex = 1;
          }
          }),
        (error => console.error('Error while trying to take a picture', error)),
        {
          quality: 100,
          sourceType: Camera.PictureSourceType.CAMERA,
          encodingType: Camera.EncodingType.PNG,
          destinationType: Camera.DestinationType.NATIVE_URI
        }
      )

    }

    function uploadPicture() {

      navigator.camera.getPicture(
        (image => {
          if (picIndex  < 4 ) {
            document.getElementById('pic'+ (picIndex+1)).src = image;
            pictures[picIndex] = image;
            picIndex++;
          }
          else {
            document.getElementById('pic1').src = image;
            pictures[0] = image;
            picIndex = 1;
          }
        }),
        (error => console.error('Error while trying to take a picture', error)),
        {
          quality: 100,
          sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
          encodingType: Camera.EncodingType.PNG,
          destinationType: Camera.DestinationType.NATIVE_URI
        }
      )

    }

    function handlePopupAction(index) {
      switch (index) {
        case 1:
          deleteImageFromNote(sessionID, document.getElementById('pic'+selectedPicID).src, DEFAULT_PIC );
          document.getElementById('pic'+selectedPicID).src = DEFAULT_PIC;
          pictures[selectedPicID-1] = DEFAULT_PIC;
          picIndex = selectedPicID - 1;
          break;
        default: window.plugins.actionsheet.hide();
      }
    }

    function showPopup(id) {

      if(document.getElementById('pic'+id).src.indexOf('default-pic.png') < 0) {
        selectedPicID = id;

        var options = {
          androidTheme: window.plugins.actionsheet.ANDROID_THEMES.THEME_DEVICE_DEFAULT_LIGHT,
          title: 'Do you want to delete this picture ?',
          androidEnableCancelButton: true,
          buttonLabels: ['Yes, I do', 'No, please don\'t'],
          position: [20, 40],
          destructiveButtonLast: true
        };

        window.plugins.actionsheet.show(options, handlePopupAction);
      }

    }

    function recordAudio(){

      navigator.device.capture.captureAudio(
        mediaFiles => console.log(mediaFiles),
        //mediaFiles => document.getElementById('note-audio').src = mediaFiles[0].fullPath,
        error => {
          console.log('Error while trying to record audio ', error);
          alert('No default audio recording app is defined on your phone. \n Install one and try again');
        },
        {
          limit: 1,
          duration: 60
        })

    }

    function recordVideo(){

      navigator.device.capture.captureVideo(
        mediaFiles => {

          let source = document.getElementById('note-source-video');
          let video  = document.getElementById('note-video');

          let media = mediaFiles[0];

          source.src = media.fullPath;
          source.type = media.type;

          video.load();
          video.hidden = false;
        },
        //mediaFiles => document.getElementById('note-audio').src = mediaFiles[0].fullPath,
        error => console.error('Error while trying to record video'),
        {
          limit: 1,
          duration: 30
        })

    }

  }

})();

// SHARE
// getSession(sessionID)
// .then(session => {
//   var options = {
//     message: 'Here are my notes from the session [ ' + session.title + ' ] taken at Devfest Nantes 2017 : \n\n'
//            + document.getElementById('note').value,
//     subject: 'Notes [ ' + session.title + ' ]',
//     files: [document.getElementById('picture').src],
//     chooserTitle: 'Pick an app'
//   }
//   window.plugins.socialsharing.shareWithOptions(options);
// })
// .catch(error => console.error('Could not find session with id ' + sessionID, error))<|endoftext|>


<commit_before>(function() {

    'use strict';

    angular.module('superdesk.monitoring', ['superdesk.api', 'superdesk.aggregate', 'superdesk.search'])
        .service('cards', CardsService)
        .controller('Monitoring', MonitoringController)
        .directive('sdMonitoringView', MonitoringViewDirective)
        .directive('sdMonitoringGroup', MonitoringGroupDirective)
        .directive('sdMonitoringGroupHeader', MonitoringGroupHeader)
        .directive('sdItemActionsMenu', ItemActionsMenu)
        .config(configureMonitoring)
        .config(configureSpikeMonitoring);

    configureMonitoring.$inject = ['superdeskProvider'];
    function configureMonitoring(superdesk) {
        superdesk
            .activity('/workspace/monitoring', {
                label: gettext('Monitoring'),
                priority: 100,
                templateUrl: 'scripts/superdesk-monitoring/views/monitoring.html',
                topTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-topnav.html',
                sideTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-sidenav.html'
            });
    }

    configureSpikeMonitoring.$inject = ['superdeskProvider'];
    function configureSpikeMonitoring(superdesk) {
        superdesk
            .activity('/workspace/spike-monitoring', {
                label: gettext('Spike Monitoring'),
                priority: 100,
                templateUrl: 'scripts/superdesk-monitoring/views/spike-monitoring.html',
                topTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-topnav.html',
                sideTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-sidenav.html'
            });
    }

    CardsService.$inject = ['api', 'search', 'session'];
    function CardsService(api, search, session) {
        this.criteria = getCriteria;

        /**
         * Get items criteria for given card
         *
         * Card can be stage/personal/saved search.
         * There can be also extra string search query
         *
         * @param {Object} card
         * @param {string} queryString
         */
        function getCriteria(card, queryString, queryParam) {
            var params = (card.type === 'search') ? JSON.parse(JSON.stringify(card.search.filter.query)): {};
            params.spike = (card.type === 'spike');
            if (card.fileType) {
                params.type = card.fileType;
            }

            if (card.type === 'search') {
                if (card.query) {
                    params.q = '(' + card.query + ') ' + card.search.filter.query.q;
                }
            } else {
                params.q = card.query;
            }

            var query = search.query(params);

            switch (card.type) {
                case 'search':
                    break;

                case 'personal':
                    query.filter({bool: {
                        must: {term: {original_creator: session.identity._id}},
                        must_not: {exists: {field: 'task.desk'}}
                    }});
                    break;

                case 'spike':
                    query.filter({term: {'task.desk': card._id}});
                    break;

                case 'highlights':
                    query.filter({and: [
                        {term: {'highlights': queryParam.highlight}}
                    ]});
                    break;

                default:
                    query.filter({term: {'task.stage': card._id}});
                    break;
            }

            if (queryString) {
                query.filter({query: {query_string: {query: queryString, lenient: false}}});
            }

            var criteria = {source: query.getCriteria()};
            criteria.source.from = 0;
            criteria.source.size = 25;
            return criteria;
        }
    }

    MonitoringController.$inject = ['$location'];
    function MonitoringController($location) {
        this.state = {};

        this.preview = preview;
        this.closePreview = closePreview;
        this.previewItem = null;

        this.singleGroup = null;
        this.viewSingleGroup = viewSingleGroup;

        this.queryParam = $location.search();

        this.edit = edit;
        this.editItem = null;

        var vm = this;

        function preview(item) {
            vm.previewItem = item;
            vm.state['with-preview'] = !!item;
        }

        function closePreview() {
            preview(null);
        }

        function edit(item) {
            vm.editItem = item;
            vm.state['with-authoring'] = !!item;
        }

        function viewSingleGroup(group) {
            vm.singleGroup = group;
        }

    }

    /**
     * Main monitoring view - list + preview
     *
     * it's a directive so that it can be put together with authoring into some container directive
     */
    function MonitoringViewDirective() {
        return {
            templateUrl: 'scripts/superdesk-monitoring/views/monitoring-view.html',
            controller: 'Monitoring',
            controllerAs: 'monitoring',
            scope: {
                type: '=',
                state: '='
            }
        };
    }

    function MonitoringGroupHeader() {
        return {
            templateUrl: 'scripts/superdesk-monitoring/views/monitoring-group-header.html'
        };
    }

    MonitoringGroupDirective.$inject = ['cards', 'api', 'superdesk', 'desks', '$timeout'];
    function MonitoringGroupDirective(cards, api, superdesk, desks, $timeout) {
        var ITEM_HEIGHT = 57,
            ITEMS_COUNT = 5,
            BUFFER = 8,
            UP = -1,
            DOWN = 1,
            ENTER_KEY = 13,
            MOVES = {
                38: UP,
                40: DOWN
            };

        return {
            templateUrl: 'scripts/superdesk-monitoring/views/monitoring-group.html',
            require: ['^sdMonitoringView', '^sdAuthoringContainer'],
            scope: {
                group: '=',
                numItems: '='
            },
            link: function(scope, elem, attrs, ctrls) {

                var monitoring = ctrls[0],
                    authoring = ctrls[1];

                scope.view = 'compact';
                scope.page = 1;
                scope.fetching = false;
                scope.cacheNextItems = [];
                scope.cachePreviousItems = [];
                scope.limited = (monitoring.singleGroup || scope.group.type === 'highlights') ? false : true;

                scope.uuid = uuid;
                scope.edit = edit;
                scope.select = select;
                scope.preview = preview;
                scope.renderNew = renderNew;
                scope.viewSingleGroup = viewSingleGroup;

                scope.$watch('group', queryItems);
                scope.$watch('group.query', queryItems);
                scope.$watch('group.fileType', queryItems);
                scope.$on('task:stage', handleStage);
                scope.$on('ingest:update', update);
                scope.$on('item:spike', update);
                scope.$on('item:unspike', update);

                var list = elem[0].getElementsByClassName('inline-content-items')[0],
                    scrollElem = elem.find('.stage-content').first();

                scrollElem.on('keydown', handleKey);
                scrollElem.on('scroll', handleScroll);
                scope.$on('$destroy', function() {
                    scrollElem.off();
                });

                var criteria,
                    updateTimeout,
                    moveTimeout;

                function handleStage(event, data) {
                    if (data.new_stage === scope.stage || data.old_stage === scope.stage) {
                        update();
                    }
                }

                function edit(item, lock) {
                    authoring.edit(item, lock);
                }

                function select(item) {
                    scope.selected = item;
                    monitoring.preview(item);
                }

                function preview(item) {
                    select(item);
                }

                function queryItems() {
                    criteria = cards.criteria(scope.group, null, monitoring.queryParam);
                    criteria.source.size = 0; // we only need to get total num of items
                    scope.loading = true;
                    scope.total = null;
                    return apiquery().then(function(items) {
                        scope.total = items._meta.total;
                        scope.$applyAsync(render);
                    })['finally'](function() {
                        scope.loading = false;
                    });
                }

                function render() {
                    var top = scrollElem[0].scrollTop,
                        start = Math.floor(top / ITEM_HEIGHT),
                        from = Math.max(0, start - BUFFER),
                        itemsCount = scope.numItems || ITEMS_COUNT,
                        to = Math.min(scope.total, start + itemsCount + BUFFER);

                    if (parseInt(list.style.height, 10) !== scope.total * ITEM_HEIGHT) {
                        list.style.height = (scope.total * ITEM_HEIGHT) + 'px';
                    }

                    criteria.source.from = from;
                    criteria.source.size = to - from;
                    return apiquery().then(function(items) {
                        scope.$applyAsync(function() {
                            if (scope.total !== items._meta.total) {
                                scope.total = items._meta.total;
                                list.style.height = (scope.total * ITEM_HEIGHT) + 'px';
                            }

                            list.style.paddingTop = (from * ITEM_HEIGHT) + 'px';
                            scope.items = merge(items._items);
                        });
                    });
                }

                function apiquery(query) {
                    return api.query('archive', query ? {source: query} : criteria);
                }

                function renderNew() {
                    scope.total += scope.newItemsCount;
                    scope.newItemsCount = 0;
                    render();
                }

                function viewSingleGroup(group) {
                    monitoring.viewSingleGroup(group);
                }

                function merge(newItems) {
                    var next = [],
                        olditems = scope.items || [];
                    angular.forEach(newItems, function(item) {
                        var old = _.find(olditems, {_id: item._id});
                        next.push(old ? angular.extend(old, item) : item);
                    });

                    return next;
                }

                function updateCurrentView() {
                    var ids = _.pluck(scope.items, '_id'),
                        query = {query: {filtered: {filter: {and: [
                            {terms: {_id: ids}},
                            {term: {'task.stage': scope.stage}}
                        ]}}}};
                    query.size = ids.length;
                    apiquery(query).then(function(items) {
                        var nextItems = _.indexBy(items._items, '_id');
                        angular.forEach(scope.items, function(item, i) {
                            var diff = nextItems[item._id] || {_deleted: 1};
                            angular.extend(item, diff);
                        });
                    });
                }

                function update() {
                    if (scrollElem[0].scrollTop || scope.selected) {
                        updateCurrentView();
                    } else {
                        render();
                    }
                }

                function handleScroll(event) {
                    $timeout.cancel(updateTimeout);
                    updateTimeout = $timeout(render, 100, false);
                }

                function handleKey(event) {
                    var code = event.keyCode || event.which;
                    if (MOVES[code]) {
                        event.preventDefault();
                        event.stopPropagation();
                        $timeout.cancel(updateTimeout);
                        move(MOVES[code], event);
                        handleScroll(); // make sure we scroll after moving
                    } else if (code === ENTER_KEY) {
                        scope.$applyAsync(function() {
                            edit(scope.selected);
                        });
                    }
                }

                function clickItem(item, event) {
                    scope.select(item);
                    if (event) {
                        event.preventDefault();
                        event.stopPropagation();
                        event.stopImmediatePropagation();
                    }
                }

                function move(diff, event) {
                    var index = _.findIndex(scope.items, scope.selected),
                        itemsCount = scope.numItems || ITEMS_COUNT,
                        nextItem,
                        nextIndex;

                    if (index === -1) {
                        nextItem = scope.items[0];
                    } else {
                        nextIndex = Math.max(0, Math.min(scope.items.length - 1, index + diff));
                        nextItem = scope.items[nextIndex];

                        $timeout.cancel(moveTimeout);
                        moveTimeout = $timeout(function() {
                            var top = scrollElem[0].scrollTop,
                                topItemIndex = Math.ceil(top / ITEM_HEIGHT),
                                bottomItemIndex = Math.floor((top + scrollElem[0].clientHeight) / ITEM_HEIGHT),
                                nextItemIndex = nextIndex + criteria.source.from;
                            if (nextItemIndex < topItemIndex) {
                                scrollElem[0].scrollTop = Math.max(0, nextItemIndex * ITEM_HEIGHT);
                            } else if (nextItemIndex >= bottomItemIndex) {
                                scrollElem[0].scrollTop = (nextItemIndex - itemsCount + 1) * ITEM_HEIGHT;
                            }
                        }, 50, false);
                    }

                    scope.$apply(function() {
                        clickItem(scope.items[nextIndex], event);
                    });
                }
            }
        };

        function uuid(item) {
            return item._id;
        }
    }

    ItemActionsMenu.$inject = ['superdesk', 'activityService', 'workflowService', 'archiveService'];
    function ItemActionsMenu(superdesk, activityService, workflowService, archiveService) {
        return {
            scope: {
                item: '=',
                active: '='
            },
            templateUrl: 'scripts/superdesk-monitoring/views/item-actions-menu.html',
            link: function(scope) {
                /**
                 * Populate scope actions when dropdown is opened.
                 *
                 * @param {boolean} isOpen
                 */
                scope.toggleActions = function(isOpen) {
                    scope.actions = isOpen ? getActions(scope.item) : scope.actions;
                    scope.open = isOpen;
                };

                /**
                 * Stope event propagation so that click on dropdown menu
                 * won't select that item for preview/authoring.
                 *
                 * @param {Event} event
                 */
                scope.stopEvent = function(event) {
                    event.stopPropagation();
                };

                scope.run = function(activity) {
                    return activityService.start(activity, {data: {item: scope.item}});
                };

                /**
                 * Get available actions for given item.
                 *
                 * This is not context aware, it will return everything.
                 *
                 * @param {object} item
                 * @return {object}
                 */
                function getActions(item) {
                    var intent = {action: 'list', type: getType(item)};
                    var groups = {};
                    superdesk.findActivities(intent, item).forEach(function(activity) {
                        if (workflowService.isActionAllowed(scope.item, activity.action)) {
                            var group = activity.group || 'default';
                            groups[group] = groups[group] || [];
                            groups[group].push(activity);
                        }
                    });
                    return groups;
                }

                /**
                 * Get actions type based on item state. Used with activity filter.
                 *
                 * @param {Object} item
                 * @return {string}
                 */
                function getType(item) {
                    return archiveService.getType(item);
                }
            }
        };
    }
})();
<commit_msg>Fix (on edit close preview)<commit_after>(function() {

    'use strict';

    angular.module('superdesk.monitoring', ['superdesk.api', 'superdesk.aggregate', 'superdesk.search'])
        .service('cards', CardsService)
        .controller('Monitoring', MonitoringController)
        .directive('sdMonitoringView', MonitoringViewDirective)
        .directive('sdMonitoringGroup', MonitoringGroupDirective)
        .directive('sdMonitoringGroupHeader', MonitoringGroupHeader)
        .directive('sdItemActionsMenu', ItemActionsMenu)
        .config(configureMonitoring)
        .config(configureSpikeMonitoring);

    configureMonitoring.$inject = ['superdeskProvider'];
    function configureMonitoring(superdesk) {
        superdesk
            .activity('/workspace/monitoring', {
                label: gettext('Monitoring'),
                priority: 100,
                templateUrl: 'scripts/superdesk-monitoring/views/monitoring.html',
                topTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-topnav.html',
                sideTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-sidenav.html'
            });
    }

    configureSpikeMonitoring.$inject = ['superdeskProvider'];
    function configureSpikeMonitoring(superdesk) {
        superdesk
            .activity('/workspace/spike-monitoring', {
                label: gettext('Spike Monitoring'),
                priority: 100,
                templateUrl: 'scripts/superdesk-monitoring/views/spike-monitoring.html',
                topTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-topnav.html',
                sideTemplateUrl: 'scripts/superdesk-dashboard/views/workspace-sidenav.html'
            });
    }

    CardsService.$inject = ['api', 'search', 'session'];
    function CardsService(api, search, session) {
        this.criteria = getCriteria;

        /**
         * Get items criteria for given card
         *
         * Card can be stage/personal/saved search.
         * There can be also extra string search query
         *
         * @param {Object} card
         * @param {string} queryString
         */
        function getCriteria(card, queryString, queryParam) {
            var params = (card.type === 'search') ? JSON.parse(JSON.stringify(card.search.filter.query)): {};
            params.spike = (card.type === 'spike');
            if (card.fileType) {
                params.type = card.fileType;
            }

            if (card.type === 'search') {
                if (card.query) {
                    params.q = '(' + card.query + ') ' + card.search.filter.query.q;
                }
            } else {
                params.q = card.query;
            }

            var query = search.query(params);

            switch (card.type) {
                case 'search':
                    break;

                case 'personal':
                    query.filter({bool: {
                        must: {term: {original_creator: session.identity._id}},
                        must_not: {exists: {field: 'task.desk'}}
                    }});
                    break;

                case 'spike':
                    query.filter({term: {'task.desk': card._id}});
                    break;

                case 'highlights':
                    query.filter({and: [
                        {term: {'highlights': queryParam.highlight}}
                    ]});
                    break;

                default:
                    query.filter({term: {'task.stage': card._id}});
                    break;
            }

            if (queryString) {
                query.filter({query: {query_string: {query: queryString, lenient: false}}});
            }

            var criteria = {source: query.getCriteria()};
            criteria.source.from = 0;
            criteria.source.size = 25;
            return criteria;
        }
    }

    MonitoringController.$inject = ['$location'];
    function MonitoringController($location) {
        this.state = {};

        this.preview = preview;
        this.closePreview = closePreview;
        this.previewItem = null;

        this.singleGroup = null;
        this.viewSingleGroup = viewSingleGroup;

        this.queryParam = $location.search();

        this.edit = edit;
        this.editItem = null;

        var vm = this;

        function preview(item) {
            vm.previewItem = item;
            vm.state['with-preview'] = !!item;
        }

        function closePreview() {
            preview(null);
        }

        function edit(item) {
            vm.editItem = item;
            vm.state['with-authoring'] = !!item;
        }

        function viewSingleGroup(group) {
            vm.singleGroup = group;
        }

    }

    /**
     * Main monitoring view - list + preview
     *
     * it's a directive so that it can be put together with authoring into some container directive
     */
    function MonitoringViewDirective() {
        return {
            templateUrl: 'scripts/superdesk-monitoring/views/monitoring-view.html',
            controller: 'Monitoring',
            controllerAs: 'monitoring',
            scope: {
                type: '=',
                state: '='
            }
        };
    }

    function MonitoringGroupHeader() {
        return {
            templateUrl: 'scripts/superdesk-monitoring/views/monitoring-group-header.html'
        };
    }

    MonitoringGroupDirective.$inject = ['cards', 'api', 'superdesk', 'desks', '$timeout'];
    function MonitoringGroupDirective(cards, api, superdesk, desks, $timeout) {
        var ITEM_HEIGHT = 57,
            ITEMS_COUNT = 5,
            BUFFER = 8,
            UP = -1,
            DOWN = 1,
            ENTER_KEY = 13,
            MOVES = {
                38: UP,
                40: DOWN
            };

        return {
            templateUrl: 'scripts/superdesk-monitoring/views/monitoring-group.html',
            require: ['^sdMonitoringView', '^sdAuthoringContainer'],
            scope: {
                group: '=',
                numItems: '='
            },
            link: function(scope, elem, attrs, ctrls) {

                var monitoring = ctrls[0],
                    authoring = ctrls[1];

                scope.view = 'compact';
                scope.page = 1;
                scope.fetching = false;
                scope.cacheNextItems = [];
                scope.cachePreviousItems = [];
                scope.limited = (monitoring.singleGroup || scope.group.type === 'highlights') ? false : true;

                scope.uuid = uuid;
                scope.edit = edit;
                scope.select = select;
                scope.preview = preview;
                scope.renderNew = renderNew;
                scope.viewSingleGroup = viewSingleGroup;

                scope.$watch('group', queryItems);
                scope.$watch('group.query', queryItems);
                scope.$watch('group.fileType', queryItems);
                scope.$on('task:stage', handleStage);
                scope.$on('ingest:update', update);
                scope.$on('item:spike', update);
                scope.$on('item:unspike', update);

                var list = elem[0].getElementsByClassName('inline-content-items')[0],
                    scrollElem = elem.find('.stage-content').first();

                scrollElem.on('keydown', handleKey);
                scrollElem.on('scroll', handleScroll);
                scope.$on('$destroy', function() {
                    scrollElem.off();
                });

                var criteria,
                    updateTimeout,
                    moveTimeout;

                function handleStage(event, data) {
                    if (data.new_stage === scope.stage || data.old_stage === scope.stage) {
                        update();
                    }
                }

                function edit(item, lock) {
                    authoring.edit(item, lock);
                    monitoring.preview(null);
                }

                function select(item) {
                    scope.selected = item;
                    monitoring.preview(item);
                }

                function preview(item) {
                    select(item);
                }

                function queryItems() {
                    criteria = cards.criteria(scope.group, null, monitoring.queryParam);
                    criteria.source.size = 0; // we only need to get total num of items
                    scope.loading = true;
                    scope.total = null;
                    return apiquery().then(function(items) {
                        scope.total = items._meta.total;
                        scope.$applyAsync(render);
                    })['finally'](function() {
                        scope.loading = false;
                    });
                }

                function render() {
                    var top = scrollElem[0].scrollTop,
                        start = Math.floor(top / ITEM_HEIGHT),
                        from = Math.max(0, start - BUFFER),
                        itemsCount = scope.numItems || ITEMS_COUNT,
                        to = Math.min(scope.total, start + itemsCount + BUFFER);

                    if (parseInt(list.style.height, 10) !== scope.total * ITEM_HEIGHT) {
                        list.style.height = (scope.total * ITEM_HEIGHT) + 'px';
                    }

                    criteria.source.from = from;
                    criteria.source.size = to - from;
                    return apiquery().then(function(items) {
                        scope.$applyAsync(function() {
                            if (scope.total !== items._meta.total) {
                                scope.total = items._meta.total;
                                list.style.height = (scope.total * ITEM_HEIGHT) + 'px';
                            }

                            list.style.paddingTop = (from * ITEM_HEIGHT) + 'px';
                            scope.items = merge(items._items);
                        });
                    });
                }

                function apiquery(query) {
                    return api.query('archive', query ? {source: query} : criteria);
                }

                function renderNew() {
                    scope.total += scope.newItemsCount;
                    scope.newItemsCount = 0;
                    render();
                }

                function viewSingleGroup(group) {
                    monitoring.viewSingleGroup(group);
                }

                function merge(newItems) {
                    var next = [],
                        olditems = scope.items || [];
                    angular.forEach(newItems, function(item) {
                        var old = _.find(olditems, {_id: item._id});
                        next.push(old ? angular.extend(old, item) : item);
                    });

                    return next;
                }

                function updateCurrentView() {
                    var ids = _.pluck(scope.items, '_id'),
                        query = {query: {filtered: {filter: {and: [
                            {terms: {_id: ids}},
                            {term: {'task.stage': scope.stage}}
                        ]}}}};
                    query.size = ids.length;
                    apiquery(query).then(function(items) {
                        var nextItems = _.indexBy(items._items, '_id');
                        angular.forEach(scope.items, function(item, i) {
                            var diff = nextItems[item._id] || {_deleted: 1};
                            angular.extend(item, diff);
                        });
                    });
                }

                function update() {
                    if (scrollElem[0].scrollTop || scope.selected) {
                        updateCurrentView();
                    } else {
                        render();
                    }
                }

                function handleScroll(event) {
                    $timeout.cancel(updateTimeout);
                    updateTimeout = $timeout(render, 100, false);
                }

                function handleKey(event) {
                    var code = event.keyCode || event.which;
                    if (MOVES[code]) {
                        event.preventDefault();
                        event.stopPropagation();
                        $timeout.cancel(updateTimeout);
                        move(MOVES[code], event);
                        handleScroll(); // make sure we scroll after moving
                    } else if (code === ENTER_KEY) {
                        scope.$applyAsync(function() {
                            edit(scope.selected);
                        });
                    }
                }

                function clickItem(item, event) {
                    scope.select(item);
                    if (event) {
                        event.preventDefault();
                        event.stopPropagation();
                        event.stopImmediatePropagation();
                    }
                }

                function move(diff, event) {
                    var index = _.findIndex(scope.items, scope.selected),
                        itemsCount = scope.numItems || ITEMS_COUNT,
                        nextItem,
                        nextIndex;

                    if (index === -1) {
                        nextItem = scope.items[0];
                    } else {
                        nextIndex = Math.max(0, Math.min(scope.items.length - 1, index + diff));
                        nextItem = scope.items[nextIndex];

                        $timeout.cancel(moveTimeout);
                        moveTimeout = $timeout(function() {
                            var top = scrollElem[0].scrollTop,
                                topItemIndex = Math.ceil(top / ITEM_HEIGHT),
                                bottomItemIndex = Math.floor((top + scrollElem[0].clientHeight) / ITEM_HEIGHT),
                                nextItemIndex = nextIndex + criteria.source.from;
                            if (nextItemIndex < topItemIndex) {
                                scrollElem[0].scrollTop = Math.max(0, nextItemIndex * ITEM_HEIGHT);
                            } else if (nextItemIndex >= bottomItemIndex) {
                                scrollElem[0].scrollTop = (nextItemIndex - itemsCount + 1) * ITEM_HEIGHT;
                            }
                        }, 50, false);
                    }

                    scope.$apply(function() {
                        clickItem(scope.items[nextIndex], event);
                    });
                }
            }
        };

        function uuid(item) {
            return item._id;
        }
    }

    ItemActionsMenu.$inject = ['superdesk', 'activityService', 'workflowService', 'archiveService'];
    function ItemActionsMenu(superdesk, activityService, workflowService, archiveService) {
        return {
            scope: {
                item: '=',
                active: '='
            },
            templateUrl: 'scripts/superdesk-monitoring/views/item-actions-menu.html',
            link: function(scope) {
                /**
                 * Populate scope actions when dropdown is opened.
                 *
                 * @param {boolean} isOpen
                 */
                scope.toggleActions = function(isOpen) {
                    scope.actions = isOpen ? getActions(scope.item) : scope.actions;
                    scope.open = isOpen;
                };

                /**
                 * Stope event propagation so that click on dropdown menu
                 * won't select that item for preview/authoring.
                 *
                 * @param {Event} event
                 */
                scope.stopEvent = function(event) {
                    event.stopPropagation();
                };

                scope.run = function(activity) {
                    return activityService.start(activity, {data: {item: scope.item}});
                };

                /**
                 * Get available actions for given item.
                 *
                 * This is not context aware, it will return everything.
                 *
                 * @param {object} item
                 * @return {object}
                 */
                function getActions(item) {
                    var intent = {action: 'list', type: getType(item)};
                    var groups = {};
                    superdesk.findActivities(intent, item).forEach(function(activity) {
                        if (workflowService.isActionAllowed(scope.item, activity.action)) {
                            var group = activity.group || 'default';
                            groups[group] = groups[group] || [];
                            groups[group].push(activity);
                        }
                    });
                    return groups;
                }

                /**
                 * Get actions type based on item state. Used with activity filter.
                 *
                 * @param {Object} item
                 * @return {string}
                 */
                function getType(item) {
                    return archiveService.getType(item);
                }
            }
        };
    }
})();
<|endoftext|>


<commit_before>var supertest = require('supertest');
var should = require('should');

// get the code to test
//var smartPayFunctions = require('../lib/smartpay-functions.js');

// point test to where service is running
//server = supertest.agent('http://localhost:4321/api/payment');

var baseUrl = 'http://localhost:4321/api/payment';
//var server = request.agent(baseUrl);

describe('Work with Payments', function () {
    it('runs health check', function (done) {
        request(baseUrl).get('/healthcheck')
            .expect(200)
            .end(function (err, res) {
                if (err) return done(err);
                expect(res.body.message).to.equal('is-payment-service running');
                done();
            });
    });
});

//describe('Payment Service', function() {
//
//    it('should return valid application data fields', function (done) {
//
//        var formFields = {};
//        var dummyAppId = 8888;
//        var dummyApplicationDetail = { payment_amount : 12.34 };
//        var dummyApplication = { unique_app_id: 1234 };
//        var dummyDocumentCount = { doc_count: 1 };

//        smartPayFunctions.addApplicationData(
//            dummyAppId,
//            formFields,
//            dummyApplicationDetail,
//            dummyApplication,
//            dummyDocumentCount, function (err, result) {
//
//            if (err) return done(err);
//
//            // should have array with inserted fields
//            result.merchantReturnData.should.equal(dummyAppId);
//            done();
//        });
//    });
//
//});
<commit_msg>Update healthcheck test message<commit_after>var supertest = require('supertest');
var should = require('should');

// get the code to test
//var smartPayFunctions = require('../lib/smartpay-functions.js');

// point test to where service is running
//server = supertest.agent('http://localhost:4321/api/payment');

var baseUrl = 'http://localhost:4321/api/payment';
//var server = request.agent(baseUrl);

describe('Work with Payments', function () {
    it('runs health check', function (done) {
        request(baseUrl).get('/healthcheck')
            .expect(200)
            .end(function (err, res) {
                if (err) return done(err);
                expect(res.body.message).to.equal('Payment Service is running');
                done();
            });
    });
});

//describe('Payment Service', function() {
//
//    it('should return valid application data fields', function (done) {
//
//        var formFields = {};
//        var dummyAppId = 8888;
//        var dummyApplicationDetail = { payment_amount : 12.34 };
//        var dummyApplication = { unique_app_id: 1234 };
//        var dummyDocumentCount = { doc_count: 1 };

//        smartPayFunctions.addApplicationData(
//            dummyAppId,
//            formFields,
//            dummyApplicationDetail,
//            dummyApplication,
//            dummyDocumentCount, function (err, result) {
//
//            if (err) return done(err);
//
//            // should have array with inserted fields
//            result.merchantReturnData.should.equal(dummyAppId);
//            done();
//        });
//    });
//
//});
<|endoftext|>