<commit_before>import test                         from 'ava';
import snapshot                     from '../../helpers/snapshot';
import Vue                          from 'vue/dist/vue.common.js';
import multiinput                   from '../../../src/lib/components/multiinput/index.vue';

const name = 'multiinput';
const component = window.morning._origin.Form.extend(multiinput);
const formValue1 = ['value1', 'value2'];
const formValue2 = ['value3', 'value4'];

test.serial('base : component snapshot', async t => {

    const vm = new Vue(component).$mount();

    t.plan(1);

    snapshot(t, vm);

});

test.serial('base : init component', async t => {

    const vm = new Vue(component).$mount();

    t.plan(2);

    t.is(vm.uiid, 2);
    t.is(component.options.name, `morning-${name}`);

});

test.serial('base : component tag name is t-*', async t => {

    const vm = new Vue(component).$mount();

    t.plan(1);

    t.is(vm.$el.tagName, `mor-${name}`.toUpperCase());

});

test.serial('form base : init component value is right when use v-model', async t => {

    const vm = new Vue({
        template : `

                <ui-${name} v-model="value1"></ui-${name}>

        `,
        data : {
            value1 : formValue1
        },
        components : {
            [`ui-${name}`] : component
        }
    });

    vm.$mount();

    t.plan(1);

    Vue.nextTick(() => {

        t.is(JSON.stringify(vm.$children[0].get()), JSON.stringify(formValue1));

    });

});

test.serial('form base : init component value is right when both use v-model and default-value', async t => {

    const vm = new Vue({
        template : `

                <ui-${name} v-model="value1" :default-value="value2"></ui-${name}>

        `,
        data : {
            value1 : formValue1,
            value2 : formValue2
        },
        components : {
            [`ui-${name}`] : component
        }
    });

    vm.$mount();

    t.plan(1);

    Vue.nextTick(() => {

        t.is(JSON.stringify(vm.$children[0].get()), JSON.stringify(formValue1));

    });

});

test.serial('form value-change : default value not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} :default-value="value" @value-change="echo"</ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        }
    });

    vm.$mount();

    t.plan(1);

    Vue.nextTick(() => {

        t.is(count, 0);

    });

});

test.serial('form value-change : set value emit event once', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo"</ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            Vue.nextTick(() => {

                t.is(count, 0);
                this.$refs.test.set(formValue2);

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : set same value not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo"</ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            this.$refs.test.set(formValue2);

            Vue.nextTick(() => {

                t.is(count, 1);

                this.$refs.test.set(formValue2);

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : set invalid value not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo"</ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            this.$refs.test.set(NaN);

            Vue.nextTick(() => {

                t.is(count, 1);
                this.$refs.test.set('asd');

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : value pass filter emit event once', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo" :max="2"</ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            this.$refs.test.set(['a', 'b', 'c']);

            Vue.nextTick(() => {

                t.is(count, 1);

                this.$refs.test.set(['a', 'b', 'c']);

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : v-model not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" v-model="value" @value-change="echo"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            Vue.nextTick(() => {

                t.is(count, 0);

            });

        }
    });

    vm.$mount();

    t.plan(1);

});

test.serial('form value-change : v-model change emit event once', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" v-model="value" @value-change="echo"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            Vue.nextTick(() => {

                t.is(count, 0);

                this.value = formValue2;

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

<commit_msg>update test<commit_after>import test                         from 'ava';
import snapshot                     from '../../helpers/snapshot';
import Vue                          from 'vue/dist/vue.common.js';
import multiinput                   from '../../../src/lib/components/multiinput/index.vue';

const name = 'multiinput';
const component = window.morning._origin.Form.extend(multiinput);
const formValue1 = ['value1', 'value2'];
const formValue2 = ['value3', 'value4'];

test.serial('base : component snapshot', async t => {

    const vm = new Vue(component).$mount();

    t.plan(1);

    snapshot(t, vm);

});

test.serial('base : init component', async t => {

    const vm = new Vue(component).$mount();

    t.plan(2);

    t.is(vm.uiid, 2);
    t.is(component.options.name, `morning-${name}`);

});

test.serial('base : component tag name is t-*', async t => {

    const vm = new Vue(component).$mount();

    t.plan(1);

    t.is(vm.$el.tagName, `mor-${name}`.toUpperCase());

});

test.serial('form base : init component value is right when use v-model', async t => {

    const vm = new Vue({
        template : `

                <ui-${name} v-model="value1"></ui-${name}>

        `,
        data : {
            value1 : formValue1
        },
        components : {
            [`ui-${name}`] : component
        }
    });

    vm.$mount();

    t.plan(1);

    Vue.nextTick(() => {

        t.is(JSON.stringify(vm.$children[0].get()), JSON.stringify(formValue1));

    });

});

test.serial('form base : init component value is right when both use v-model and default-value', async t => {

    const vm = new Vue({
        template : `

                <ui-${name} v-model="value1" :default-value="value2"></ui-${name}>

        `,
        data : {
            value1 : formValue1,
            value2 : formValue2
        },
        components : {
            [`ui-${name}`] : component
        }
    });

    vm.$mount();

    t.plan(1);

    Vue.nextTick(() => {

        t.is(JSON.stringify(vm.$children[0].get()), JSON.stringify(formValue1));

    });

});

test.serial('form value-change : default value not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} :default-value="value" @value-change="echo"</ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        }
    });

    vm.$mount();

    t.plan(1);

    Vue.nextTick(() => {

        t.is(count, 0);

    });

});

test.serial('form value-change : set value emit event once', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            Vue.nextTick(() => {

                t.is(count, 0);
                this.$refs.test.set(formValue2);

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : set same value not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            this.$refs.test.set(formValue2);

            Vue.nextTick(() => {

                t.is(count, 1);

                this.$refs.test.set(formValue2);

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : set invalid value not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            this.$refs.test.set(NaN);

            Vue.nextTick(() => {

                t.is(count, 1);
                this.$refs.test.set('asd');

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : value pass filter emit event once', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" :default-value="value" @value-change="echo" :max="2"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            this.$refs.test.set(['a', 'b', 'c']);

            Vue.nextTick(() => {

                t.is(count, 1);

                this.$refs.test.set(['a', 'b', 'c']);

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

test.serial('form value-change : v-model not emit event', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" v-model="value" @value-change="echo"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            Vue.nextTick(() => {

                t.is(count, 0);

            });

        }
    });

    vm.$mount();

    t.plan(1);

});

test.serial('form value-change : v-model change emit event once', async t => {

    let count = 0;

    const vm = new Vue({
        template : `

                <ui-${name} ref="test" v-model="value" @value-change="echo"></ui-${name}>

        `,
        data : {
            value : formValue1
        },
        components : {
            [`ui-${name}`] : component
        },
        methods : {
            echo : function () {

                count++;

            }
        },
        mounted : function () {

            Vue.nextTick(() => {

                t.is(count, 0);

                this.value = formValue2;

                Vue.nextTick(() => {

                    t.is(count, 1);

                });

            });

        }
    });

    vm.$mount();

    t.plan(2);

});

<|endoftext|>


<commit_before>const { expect } = require('chai')

const translations = require('../../../app/js/translations')

describe('translations', function() {
  beforeEach(function() {
    this.translations = translations.setup({
      subdomainLang: {
        www: { lngCode: 'en', url: 'www.sharelatex.com' },
        fr: { lngCode: 'fr', url: 'fr.sharelatex.com' },
        da: { lngCode: 'da', url: 'da.sharelatex.com' }
      }
    })

    this.req = {
      originalUrl: "doesn'tmatter.sharelatex.com/login",
      headers: {
        'accept-language': ''
      }
    }
    this.res = {}
  })

  describe('setLangBasedOnDomainMiddlewear', function() {
    it('should set the lang to french if the domain is fr', function(done) {
      this.req.url = 'fr.sharelatex.com/login'
      this.req.headers.host = 'fr.sharelatex.com'
      this.translations.expressMiddlewear(this.req, this.req, () => {
        this.translations.setLangBasedOnDomainMiddlewear(
          this.req,
          this.res,
          () => {
            expect(this.req.lng).to.equal('fr')
            done()
          }
        )
      })
    })

    describe('showUserOtherLng', function() {
      it('should set it to true if the language based on headers is different to lng', function(done) {
        this.req.headers['accept-language'] = 'da, en-gb;q=0.8, en;q=0.7'
        this.req.url = 'fr.sharelatex.com/login'
        this.req.headers.host = 'fr.sharelatex.com'
        this.translations.expressMiddlewear(this.req, this.req, () => {
          this.translations.setLangBasedOnDomainMiddlewear(
            this.req,
            this.res,
            () => {
              expect(this.req.showUserOtherLng).to.equal('da')
              done()
            }
          )
        })
      })

      it('should not set prop', function(done) {
        this.req.headers['accept-language'] = 'da, en-gb;q=0.8, en;q=0.7'
        this.req.url = 'da.sharelatex.com/login'
        this.req.headers.host = 'da.sharelatex.com'
        this.translations.expressMiddlewear(this.req, this.req, () => {
          this.translations.setLangBasedOnDomainMiddlewear(
            this.req,
            this.res,
            () => {
              expect(this.req.showUserOtherLng).to.not.exist
              done()
            }
          )
        })
      })
    })
  })
})
<commit_msg>Add test for setLng query param behaviour<commit_after>const { expect } = require('chai')

const translations = require('../../../app/js/translations')

describe('translations', function() {
  beforeEach(function() {
    this.translations = translations.setup({
      subdomainLang: {
        www: { lngCode: 'en', url: 'www.sharelatex.com' },
        fr: { lngCode: 'fr', url: 'fr.sharelatex.com' },
        da: { lngCode: 'da', url: 'da.sharelatex.com' }
      }
    })

    this.req = {
      originalUrl: "doesn'tmatter.sharelatex.com/login",
      headers: {
        'accept-language': ''
      }
    }
    this.res = {}
  })

  describe('setLangBasedOnDomainMiddlewear', function() {
    it('should set the lang to french if the domain is fr', function(done) {
      this.req.url = 'fr.sharelatex.com/login'
      this.req.headers.host = 'fr.sharelatex.com'
      this.translations.expressMiddlewear(this.req, this.req, () => {
        this.translations.setLangBasedOnDomainMiddlewear(
          this.req,
          this.res,
          () => {
            expect(this.req.lng).to.equal('fr')
            done()
          }
        )
      })
    })

    it('ignores domain if setLng query param is set', function(done) {
      this.req.originalUrl = 'fr.sharelatex.com/login?setLng=en'
      this.req.url = 'fr.sharelatex.com/login'
      this.req.headers.host = 'fr.sharelatex.com'
      this.translations.expressMiddlewear(this.req, this.req, () => {
        this.translations.setLangBasedOnDomainMiddlewear(
          this.req,
          this.res,
          () => {
            expect(this.req.lng).to.equal('en')
            done()
          }
        )
      })
    })

    describe('showUserOtherLng', function() {
      it('should set it to true if the language based on headers is different to lng', function(done) {
        this.req.headers['accept-language'] = 'da, en-gb;q=0.8, en;q=0.7'
        this.req.url = 'fr.sharelatex.com/login'
        this.req.headers.host = 'fr.sharelatex.com'
        this.translations.expressMiddlewear(this.req, this.req, () => {
          this.translations.setLangBasedOnDomainMiddlewear(
            this.req,
            this.res,
            () => {
              expect(this.req.showUserOtherLng).to.equal('da')
              done()
            }
          )
        })
      })

      it('should not set prop', function(done) {
        this.req.headers['accept-language'] = 'da, en-gb;q=0.8, en;q=0.7'
        this.req.url = 'da.sharelatex.com/login'
        this.req.headers.host = 'da.sharelatex.com'
        this.translations.expressMiddlewear(this.req, this.req, () => {
          this.translations.setLangBasedOnDomainMiddlewear(
            this.req,
            this.res,
            () => {
              expect(this.req.showUserOtherLng).to.not.exist
              done()
            }
          )
        })
      })
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

var assert = require('chai').assert;
var Trader = require('../../lib/trader.js');
var PostgresqlInterface = require('../../lib/postgresql_interface.js');

var db = 'psql://lamassu:lamassu@localhost/lamassu-test';
var psqlInterface = new PostgresqlInterface(db);

var RATE = 100;
var CURRENCY = 'USD';
var SATOSHI_FACTOR = Math.pow(10, 8);
var LOW_BALANCE_MARGIN = 1.2;
var COMMISSION = 1.1;

var settings = {
  currency: CURRENCY,
  lowBalanceMargin: LOW_BALANCE_MARGIN,
  commission: COMMISSION
};

describe('trader/fiatBalance', function() {
  it('should calculate balance correctly with transfer exchange only', function() {
    var trader = new Trader(db);
    trader.configure({
      exchanges: {
        plugins: {
          current: {
            transfer: 'blockchain',
            ticker: 'bitpay'
          },
          settings: { blockchain: {}, bitpay: {} }
        },
        settings: settings
      }
    });

    // We have 2 bitcoins, want to trade 1 bitcoin for 100 fiat
    trader.balance = {
      transferBalance: 2 * SATOSHI_FACTOR,
      tradeBalance: null
    };
    trader.rates[CURRENCY] = { rate: RATE };

    var balance = trader.fiatBalance(1 * SATOSHI_FACTOR, 100);
    assert.equal(balance, (100 / LOW_BALANCE_MARGIN) * COMMISSION);
  });
});
<commit_msg>Change the numbers around a bit<commit_after>'use strict';

var assert = require('chai').assert;
var Trader = require('../../lib/trader.js');
var PostgresqlInterface = require('../../lib/postgresql_interface.js');

var db = 'psql://lamassu:lamassu@localhost/lamassu-test';
var psqlInterface = new PostgresqlInterface(db);

var RATE = 101;
var CURRENCY = 'USD';
var SATOSHI_FACTOR = Math.pow(10, 8);
var LOW_BALANCE_MARGIN = 1.2;
var COMMISSION = 1.1;

var settings = {
  currency: CURRENCY,
  lowBalanceMargin: LOW_BALANCE_MARGIN,
  commission: COMMISSION
};

describe('trader/fiatBalance', function() {
  it('should calculate balance correctly with transfer exchange only', function() {
    var trader = new Trader(db);
    trader.configure({
      exchanges: {
        plugins: {
          current: {
            transfer: 'blockchain',
            ticker: 'bitpay'
          },
          settings: { blockchain: {}, bitpay: {} }
        },
        settings: settings
      }
    });

    // We have 3 bitcoins, want to trade 1 bitcoin for 100 fiat
    trader.balance = {
      transferBalance: 3 * SATOSHI_FACTOR,
      tradeBalance: null
    };
    trader.rates[CURRENCY] = { rate: RATE };

    var balance = trader.fiatBalance(1 * SATOSHI_FACTOR, 100);
    assert.equal(balance, (202 / LOW_BALANCE_MARGIN) * COMMISSION);
  });
});
<|endoftext|>


<commit_before>// This easy console wrapper introduces the logging level to console for
// preventing console outputs caused when we purposely test the code path
// including console outputs.
//
// Example: Prevent the console warnings caused by Color.setStyle().
//   const c = new Color();
//   console.level = CONSOLE_LEVEL.ERROR;
//   c.setStyle( 'rgba(255,0,0,0.5)' );
//   console.level = CONSOLE_LEVEL.DEFAULT;
//
// See https://github.com/mrdoob/three.js/issues/20760#issuecomment-735190998

export const CONSOLE_LEVEL = {
	OFF : 0,
    ERROR : 1,
    WARN : 2,
    LOG : 3,
    INFO : 4,
    DEBUG : 5,
	ALL: 6,
	DEFAULT: 6
};

console.level = CONSOLE_LEVEL.DEFAULT;

// Save the original methods
console._error = console.error;
console._warn = console.warn;
console._log = console.log;
console._info = console.info;
console._debug = console.debug;

// Wrap console methods
console.error = function () {
  if (this.level >= CONSOLE_LEVEL.ERROR) this._error.apply(this, arguments);
};

console.warn = function () {
  if (this.level >= CONSOLE_LEVEL.WARN) this._warn.apply(this, arguments);
};

console.log = function () {
  if (this.level >= CONSOLE_LEVEL.LOG) this._log.apply(this, arguments);
};

console.info = function () {
  if (this.level >= CONSOLE_LEVEL.INFO) this._info.apply(this, arguments);
};

console.debug = function () {
  if (this.level >= CONSOLE_LEVEL.DEBUG) this._debug.apply(this, arguments);
};
<commit_msg>Tests: Formatting in console-wrapper<commit_after>// This easy console wrapper introduces the logging level to console for
// preventing console outputs caused when we purposely test the code path
// including console outputs.
//
// Example: Prevent the console warnings caused by Color.setStyle().
//   const c = new Color();
//   console.level = CONSOLE_LEVEL.ERROR;
//   c.setStyle( 'rgba(255,0,0,0.5)' );
//   console.level = CONSOLE_LEVEL.DEFAULT;
//
// See https://github.com/mrdoob/three.js/issues/20760#issuecomment-735190998

export const CONSOLE_LEVEL = {
	OFF : 0,
	ERROR : 1,
	WARN : 2,
	LOG : 3,
	INFO : 4,
	DEBUG : 5,
	ALL: 6,
	DEFAULT: 6
};

console.level = CONSOLE_LEVEL.DEFAULT;

// Save the original methods
console._error = console.error;
console._warn = console.warn;
console._log = console.log;
console._info = console.info;
console._debug = console.debug;

// Wrap console methods
console.error = function () {

	if ( this.level >= CONSOLE_LEVEL.ERROR ) this._error.apply( this, arguments );

};

console.warn = function () {

	if ( this.level >= CONSOLE_LEVEL.WARN ) this._warn.apply( this, arguments );

};

console.log = function () {

	if ( this.level >= CONSOLE_LEVEL.LOG ) this._log.apply( this, arguments );

};

console.info = function () {

	if ( this.level >= CONSOLE_LEVEL.INFO ) this._info.apply( this, arguments );

};

console.debug = function () {

	if ( this.level >= CONSOLE_LEVEL.DEBUG ) this._debug.apply( this, arguments );

};
<|endoftext|>


<commit_before>function epicDetailsController ($scope, $http, $q, $location) {
    var forecast = {
        time: 28, //how many days to look back in the project
        epics: 4,  //number of epics (1 would be all resources applied to the epic)
        //sprintLength: 7 //number of days in a sprint
    };

	var notStartedNames = ["To Do", "Open"];

    $scope.contextPath = jQuery('meta[name="ajs-context-path"]').attr('content');
    $scope.key = $location.search().epic;
    $scope.epicName = '';
    $scope.fullStories = []; // the full list of stories
    $scope.stories = []; // the list of stories in the current date range
    $scope.notStarted = 0;
    $scope.inProgress = 0;
    $scope.done = 0;
	$scope.averageTime = 0;

    $scope.workType = 1;

    $scope.$watch('workType', function() {
    	$scope.refresh();
    });

    $scope.points = [[],{}];
    $scope.forecastRate = 0;

    //map from constant name to custom field name
    var fieldMap = {
        'Epic Name': null,
        'Story Points': null
    };

    var epicQuery = $scope.contextPath + '/rest/api/2/';
    var storiesQuery = $scope.contextPath + '/rest/api/2/search?jql=';

    if($scope.key.indexOf('-') != -1) {
        epicQuery += 'issue';
        storiesQuery += '"Epic Link"=' + $scope.key;
    }
    else {
        epicQuery += 'project';
        storiesQuery += 'project=' + $scope.key + ' and "Epic Link" is empty and issuetype not in (Epic, Sub-task)';
    }

    epicQuery += '/' + $scope.key;
    storiesQuery += ' order by resolutiondate desc';

    $q.all([
        $http.get(epicQuery),
        $http.get(storiesQuery),
        $http.get($scope.contextPath + '/rest/api/2/field')
    ]).then(function(results) {
        var epic = results[0].data;
        var stories = results[1].data;
        var fields = results[2].data;

        $scope.setForecastRate(epic);

        //get the rest of the stories if there are more
        var maxResults = stories.maxResults;
        var total = stories.total;

        if(maxResults < total) {
            var requests = [];
            for(var i = maxResults; i < total; i += maxResults) {
                requests.push($http.get(storiesQuery + '&startAt=' + i));
            }

            $q.all(requests).then(function(results) {
                //add the new stories to the list
                angular.forEach(results, function(e, i) {
                    $scope.fullStories = $scope.fullStories.concat(e.data.issues);
                    $scope.stories = $scope.stories.concat(e.data.issues);
                });

                //refresh the display
                $scope.refresh();
            });
        }

        //setup field map
        angular.forEach(fieldMap, function(value, key) {
            angular.forEach(fields, function(elem, index) {
                if(key === elem.name) {
                    fieldMap[key] = elem.id;
                }
            });
        });

        if($scope.key.indexOf('-') != -1) {
            $scope.epicName = getField(epic.fields, 'Epic Name');
        }
        else {
            $scope.epicName = 'Other stories (' + epic.name + ')';
        }

        $scope.fullStories = stories.issues;
        $scope.stories = $scope.fullStories;

        $scope.refresh();

    });

    function getField(data, field) {
        return data[fieldMap[field]];
    }

    // count the number of not started, in progress, and done stories
    function countStories(stories) {
        $scope.notStarted = 0;
        $scope.inProgress = 0;
        $scope.done = 0;

    	angular.forEach(stories, function(story, index) {
    		var resolution = story.fields.resolutiondate;
    		if (resolution !== undefined && resolution !== null) {
    			$scope.done += getValue(story);
    		} else if (jQuery.inArray(story.fields.status.name, notStartedNames) != -1) {
    			$scope.notStarted += getValue(story);
    		} else {
    			$scope.inProgress += getValue(story);
    		}
    	});
    }

    // creates a list of (date, number) pairs
    function getProgressList(stories) {
        var list = [];

        angular.forEach(stories, function(story, index) {
            var value = getValue(story);
            list.push({
                date: Date.parse(story.fields.created),
                number: value
            });

            var resolution = story.fields.resolutiondate;
            if(resolution !== undefined && resolution !== null) {
                list.push({
                    date: Date.parse(story.fields.resolutiondate),
                    number: -value
                });
            }
        });

        list.push({
            date: new Date().getTime(),
            number: 0
        });

        return list;
    }

    // get the value of the story based on which work type is selected
    function getValue(story) {
        switch($scope.workType) {
        case 1:
            return 1;
        case 2:
            var points = getField(story.fields, 'Story Points');
            return (points !== undefined && points !== null) ? points : 0;
        case 3:
            var resolution = story.fields.resolutiondate;
            var time = story.fields.aggregateprogress.total;

            if(resolution !== undefined && resolution !== null) {
                time = story.fields.aggregateprogress.progress;
            }

            return (time / 3600);
        }
    }

    function getAverageTime(stories) {
    	var completedStories = 0;
    	var sumTime = 0;

        var day = 1000 * 60 * 60 * 24;
        var week = day * 7;

    	angular.forEach(stories, function(story, index) {
    		if(story.fields.resolutiondate !== null) {
    			completedStories++;
    			var completedTime = Date.parse(story.fields.resolutiondate) - Date.parse(story.fields.created);

                completedTime -= (2 * day * Math.floor(completedTime / week));
                completedTime /= 3;

    			sumTime+= completedTime;
            }
        });

		if(completedStories !== 0) {
        	return (sumTime/(completedStories* 60 * 60 * 1000));
        }
        return 0;
    }

    // format the given number for display
    $scope.format = function(number) {
    	if ($scope.workType == 3) {
    		return number.toFixed(2);
    	}
    	return number;
    };

    // update the story counts and chart points
    $scope.refresh = function() {
    	countStories($scope.stories);
    	$scope.averageTime = getAverageTime($scope.stories).toFixed(2);

    	// update points using full story list, so graph doesn't shrink
        var points = getProgressList($scope.fullStories);
        points.sort(function(a, b) {
            return a.date - b.date;
        });
        $scope.points = [[],{
            lines: { show: true, steps: false },
            points: { show: true },
            data: []
        }];
        var runningTotal = 0;
        angular.forEach(points, function(elem, index) {
            runningTotal += elem.number;
            $scope.points[0].push([elem.date, runningTotal]);
        });

        //set the second series data to the forecasted list
        var temp = getAverageTime($scope.fullStories);
        temp *= 3;
        temp += (temp/(5 * 24)) * 48;
        $scope.points[1].data = getForecastLine($scope.points[0][$scope.points[0].length - 1], temp);
    };

    //nicely format the date string
    $scope.doneDate = function(date) {
        if(date !== undefined && date !== null) {
            return new Date(Date.parse(date)).toLocaleString();
        }
        else {
            return 'unresolved';
        }
    };

    function getForecastLine(startPoint, averageTime) {
        var stories = $scope.notStarted + $scope.inProgress;
        return averageTime > 0 && stories > 0 ? [startPoint, [startPoint[0] + (stories * averageTime * 1000 * 60 * 60), 0]] : [];
    }

    $scope.setForecastRate = function(epic) {
        var projectKey = epic.key;
        if(epic.key.indexOf('-') != -1) {
            projectKey = epic.fields.project.key;
        }

        var restCall = $scope.contextPath + '/rest/api/2/search?jql={1}>=-' + forecast.time + 'd and project=' + projectKey + ' and status changed';

        $q.all([
            $http.get(restCall.replace('{1}', 'created')),
            $http.get(restCall.replace('{1}', 'resolved'))
        ]).then(function(results) {
            //console.log(results);

            $scope.forecastRate = (results[0].data.total - results[1].data.total) / (forecast.epics * forecast.time);
            $scope.refresh();
        });
    };
}

// Directive for creating charts
// Creates a chart with an overview chart for selecting time ranges
function chartDirective() {
    return {
        restrict: 'E',
        template: "

" +
        		  "

",
        link: function(scope, elem, attrs) {
            var chart = null;
            var overview = null;

            var opts = {
                xaxis: {
                    ticks: function(axis) {
                        var min = axis.min;
                        var step = Math.floor((axis.max - axis.min) / 4);

                        var ticks = [];

                        for(var i = 0; i < 5; i++) {
                            ticks.push(min);
                            min += step;
                        }
                        return ticks;
                    },
                    tickFormatter: function(val, axis) {
                        var range = axis.max - axis.min;
                        var day = 1000 * 60 * 60 * 24;

                        var date = new Date(val);

                        if(range >= 4 * day) {
                            return date.toLocaleDateString() + '
 ';//hack to force using up som whitespace
                        }
                        else if(range >= day) {
                            return date.toLocaleDateString() + '
' + date.toLocaleTimeString();
                        }
                        else {
                            return date.toLocaleTimeString() + '
 ';
                        }
                    }

                },
                yaxis: {
                    minTickSize: 1,
                    tickFormatter: function(val, axis) {
                        return Math.floor(parseFloat(val));
                    }
                },
                selection: {
    				mode: "x"
    			},
                series: {
                    lines: {
                        steps: true
                    }
                }
            };

            var overviewOpts = {
            	series: {
        			lines: {
                        steps: true,
        				show: true,
        				lineWidth: 1
        			},
        			shadowSize: 0
       			},
       			xaxis: {
       				ticks: [],
       				mode: "time"
        		},
        		yaxis: {
        			ticks: [],
       				min: 0,
       				autoscaleMargin: 0.1
       			},
        		selection: {
        			mode: "x"
       			}
            };

            scope.$watch(attrs.ngModel, function(v) {
                if(!chart) {
                	var chartElem = jQuery('#chart');
                	var overviewElem = jQuery('#overview');

                    chart = jQuery.plot(chartElem, v, opts);
                    overview = jQuery.plot(overviewElem, v, overviewOpts);
                    chartElem.show();
                    overviewElem.show();
                    elem.show();
                }
                else {

                    chart.setData(v);
                    chart.setupGrid();
                    chart.draw();
                    overview.setData(v);
                    overview.setupGrid();
                    overview.draw();
                }
            });

            jQuery("#chart").bind("plotselected", function (event, ranges) {

    			// do the zooming
    			jQuery.each(chart.getXAxes(), function(_, axis) {
    				var opts = axis.options;
    				opts.min = ranges.xaxis.from;
    				opts.max = ranges.xaxis.to;
    				zoom(opts.min, opts.max);
    			});
    			chart.setupGrid();
    			chart.draw();
    			chart.clearSelection();

    			// don't fire event on the overview to prevent eternal loop

    			overview.setSelection(ranges, true);
    		});
    		jQuery("#overview").bind("plotselected", function (event, ranges) {
    			chart.setSelection(ranges);
    		});

    		// zoom to the given minimum and maximum millisecond values
    		// update the current data to be a subset between the values
    		function zoom(min, max) {
    			scope.stories = [];
    			angular.forEach(scope.fullStories, function(story, index) {
    				var created = Date.parse(story.fields.created);
    				var resolved = story.fields.resolutiondate !== null ? Date.parse(story.fields.resolutiondate) : null;
    				if (created <= max && (resolved === null || resolved >= min)) {
    					scope.stories.push(story);
    				}
    			});
    			// refresh the page, wrap in apply so that page updates
    			scope.$apply(function() {
    				scope.refresh();
    			});
    		}
        }
    };
}

<commit_msg>added lines for creation, resolutions<commit_after>function epicDetailsController ($scope, $http, $q, $location) {
    var forecast = {
        time: 28, //how many days to look back in the project
        epics: 4,  //number of epics (1 would be all resources applied to the epic)
        //sprintLength: 7 //number of days in a sprint
    };

	var notStartedNames = ["To Do", "Open"];

    $scope.contextPath = jQuery('meta[name="ajs-context-path"]').attr('content');
    $scope.key = $location.search().epic;
    $scope.epicName = '';
    $scope.fullStories = []; // the full list of stories
    $scope.stories = []; // the list of stories in the current date range
    $scope.notStarted = 0;
    $scope.inProgress = 0;
    $scope.done = 0;
	$scope.averageTime = 0;
	$scope.chartMin = 0;
	$scope.chartMax = 0;

    $scope.workType = 1;

    $scope.$watch('workType', function() {
    	$scope.refresh();
    });

    $scope.points = [[],{}];
    $scope.forecastRate = 0;

    //map from constant name to custom field name
    var fieldMap = {
        'Epic Name': null,
        'Story Points': null
    };

    var epicQuery = $scope.contextPath + '/rest/api/2/';
    var storiesQuery = $scope.contextPath + '/rest/api/2/search?jql=';

    if($scope.key.indexOf('-') != -1) {
        epicQuery += 'issue';
        storiesQuery += '"Epic Link"=' + $scope.key;
    }
    else {
        epicQuery += 'project';
        storiesQuery += 'project=' + $scope.key + ' and "Epic Link" is empty and issuetype not in (Epic, Sub-task)';
    }

    epicQuery += '/' + $scope.key;
    storiesQuery += ' order by resolutiondate desc';

    $q.all([
        $http.get(epicQuery),
        $http.get(storiesQuery),
        $http.get($scope.contextPath + '/rest/api/2/field')
    ]).then(function(results) {
        var epic = results[0].data;
        var stories = results[1].data;
        var fields = results[2].data;

        $scope.setForecastRate(epic);

        //get the rest of the stories if there are more
        var maxResults = stories.maxResults;
        var total = stories.total;

        if(maxResults < total) {
            var requests = [];
            for(var i = maxResults; i < total; i += maxResults) {
                requests.push($http.get(storiesQuery + '&startAt=' + i));
            }

            $q.all(requests).then(function(results) {
                //add the new stories to the list
                angular.forEach(results, function(e, i) {
                    $scope.fullStories = $scope.fullStories.concat(e.data.issues);
                    $scope.stories = $scope.stories.concat(e.data.issues);
                });

                //refresh the display
                $scope.refresh();
            });
        }

        //setup field map
        angular.forEach(fieldMap, function(value, key) {
            angular.forEach(fields, function(elem, index) {
                if(key === elem.name) {
                    fieldMap[key] = elem.id;
                }
            });
        });

        if($scope.key.indexOf('-') != -1) {
            $scope.epicName = getField(epic.fields, 'Epic Name');
        }
        else {
            $scope.epicName = 'Other stories (' + epic.name + ')';
        }

        $scope.fullStories = stories.issues;
        $scope.stories = $scope.fullStories;

        $scope.refresh();

    });

    function getField(data, field) {
        return data[fieldMap[field]];
    }

    // count the number of not started, in progress, and done stories
    function countStories(stories) {
        $scope.notStarted = 0;
        $scope.inProgress = 0;
        $scope.done = 0;

    	angular.forEach(stories, function(story, index) {
    		var resolution = story.fields.resolutiondate;
    		if (resolution !== undefined && resolution !== null) {
    			$scope.done += getValue(story);
    		} else if (jQuery.inArray(story.fields.status.name, notStartedNames) != -1) {
    			$scope.notStarted += getValue(story);
    		} else {
    			$scope.inProgress += getValue(story);
    		}
    	});
    }

    // creates a list of (date, number) pairs
    function getProgressList(stories) {
        var list = [];

        angular.forEach(stories, function(story, index) {
            var value = getValue(story);
            list.push({
                date: Date.parse(story.fields.created),
                number: value
            });

            var resolution = story.fields.resolutiondate;
            if(resolution !== undefined && resolution !== null) {
                list.push({
                    date: Date.parse(story.fields.resolutiondate),
                    number: -value
                });
            }
        });

        list.push({
            date: new Date().getTime(),
            number: 0
        });

        return list;
    }

    // get the value of the story based on which work type is selected
    function getValue(story) {
        switch($scope.workType) {
        case 1:
            return 1;
        case 2:
            var points = getField(story.fields, 'Story Points');
            return (points !== undefined && points !== null) ? points : 0;
        case 3:
            var resolution = story.fields.resolutiondate;
            var time = story.fields.aggregateprogress.total;

            if(resolution !== undefined && resolution !== null) {
                time = story.fields.aggregateprogress.progress;
            }

            return (time / 3600);
        }
    }

    function getAverageTime(stories) {
    	var completedStories = 0;
    	var sumTime = 0;

        var day = 1000 * 60 * 60 * 24;
        var week = day * 7;

    	angular.forEach(stories, function(story, index) {
    		if(story.fields.resolutiondate !== null) {
    			completedStories++;
    			var completedTime = Date.parse(story.fields.resolutiondate) - Date.parse(story.fields.created);

                completedTime -= (2 * day * Math.floor(completedTime / week));
                completedTime /= 3;

    			sumTime+= completedTime;
            }
        });

		if(completedStories !== 0) {
        	return (sumTime/(completedStories* 60 * 60 * 1000));
        }
        return 0;
    }

    // format the given number for display
    $scope.format = function(number) {
    	if ($scope.workType == 3) {
    		return number.toFixed(2);
    	}
    	return number;
    };

    // update the story counts and chart points
    $scope.refresh = function() {
    	countStories($scope.stories);
    	$scope.averageTime = getAverageTime($scope.stories).toFixed(2);

    	// update points using full story list, so graph doesn't shrink
        var points = getProgressList($scope.fullStories);
        points.sort(function(a, b) {
            return a.date - b.date;
        });
        $scope.points = [[],{
            lines: { show: true, steps: false },
            points: { show: true },
            data: []
        }];
        var runningTotal = 0;
        angular.forEach(points, function(elem, index) {
            runningTotal += elem.number;
            $scope.points[0].push([elem.date, runningTotal]);
        });

        //set the second series data to the forecasted list
        var temp = getAverageTime($scope.fullStories);
        temp *= 3;
        temp += (temp/(5 * 24)) * 48;
        $scope.points[1].data = getForecastLine($scope.points[0][$scope.points[0].length - 1], temp);

        $scope.points.push(getDataPoints(true));
        $scope.points.push(getDataPoints(false));
    };

    // return a list of points with numbers associated with dates for either story creation
    // or resolution numbers, depending on the given boolean
    function getDataPoints(creation) {
    	var points = [];
    	var numPoints = 5;
    	// if not zoomed in, set chart min and max
    	if ($scope.chartMin == $scope.chartMax) {
    		$scope.chartMin = $scope.points[0][0][0];
    		$scope.chartMax = $scope.points[0][$scope.points[0].length - 1][0];
    	}

    	var range = ($scope.chartMax - $scope.chartMin) / numPoints;
    	for (var i = 0; i < numPoints; i++) {
    		points.push([($scope.chartMin + (i + 1) * range), 0]);
    	}
    	angular.forEach($scope.stories, function(story, index) {
    		var date = Date.parse(creation ? story.fields.created : story.fields.resolutiondate);
    		if (date > $scope.chartMin && date < $scope.chartMax) {
    			var i = Math.floor((date - $scope.chartMin) / range);
    			points[i][1]++;
    		}
    	});
    	return points;
    }

    //nicely format the date string
    $scope.doneDate = function(date) {
        if(date !== undefined && date !== null) {
            return new Date(Date.parse(date)).toLocaleString();
        }
        else {
            return 'unresolved';
        }
    };

    function getForecastLine(startPoint, averageTime) {
        var stories = $scope.notStarted + $scope.inProgress;
        return averageTime > 0 && stories > 0 ? [startPoint, [startPoint[0] + (stories * averageTime * 1000 * 60 * 60), 0]] : [];
    }

    $scope.setForecastRate = function(epic) {
        var projectKey = epic.key;
        if(epic.key.indexOf('-') != -1) {
            projectKey = epic.fields.project.key;
        }

        var restCall = $scope.contextPath + '/rest/api/2/search?jql={1}>=-' + forecast.time + 'd and project=' + projectKey + ' and status changed';

        $q.all([
            $http.get(restCall.replace('{1}', 'created')),
            $http.get(restCall.replace('{1}', 'resolved'))
        ]).then(function(results) {
            //console.log(results);

            $scope.forecastRate = (results[0].data.total - results[1].data.total) / (forecast.epics * forecast.time);
            $scope.refresh();
        });
    };
}

// Directive for creating charts
// Creates a chart with an overview chart for selecting time ranges
function chartDirective() {
    return {
        restrict: 'E',
        template: "

" +
        		  "

",
        link: function(scope, elem, attrs) {
            var chart = null;
            var overview = null;

            var opts = {
                xaxis: {
                    ticks: function(axis) {
                        var min = axis.min;
                        var step = Math.floor((axis.max - axis.min) / 4);

                        var ticks = [];

                        for(var i = 0; i < 5; i++) {
                            ticks.push(min);
                            min += step;
                        }
                        return ticks;
                    },
                    tickFormatter: function(val, axis) {
                        var range = axis.max - axis.min;
                        var day = 1000 * 60 * 60 * 24;

                        var date = new Date(val);

                        if(range >= 4 * day) {
                            return date.toLocaleDateString() + '
 ';//hack to force using up som whitespace
                        }
                        else if(range >= day) {
                            return date.toLocaleDateString() + '
' + date.toLocaleTimeString();
                        }
                        else {
                            return date.toLocaleTimeString() + '
 ';
                        }
                    }

                },
                yaxis: {
                    minTickSize: 1,
                    tickFormatter: function(val, axis) {
                        return Math.floor(parseFloat(val));
                    }
                },
                selection: {
    				mode: "x"
    			},
                series: {
                    lines: {
                        steps: true
                    }
                }
            };

            var overviewOpts = {
            	series: {
        			lines: {
                        steps: true,
        				show: true,
        				lineWidth: 1
        			},
        			shadowSize: 0
       			},
       			xaxis: {
       				ticks: [],
       				mode: "time"
        		},
        		yaxis: {
        			ticks: [],
       				min: 0,
       				autoscaleMargin: 0.1
       			},
        		selection: {
        			mode: "x"
       			}
            };

            scope.$watch(attrs.ngModel, function(v) {
                if(!chart) {
                	var chartElem = jQuery('#chart');
                	var overviewElem = jQuery('#overview');

                    chart = jQuery.plot(chartElem, v, opts);
                    overview = jQuery.plot(overviewElem, v, overviewOpts);
                    chartElem.show();
                    overviewElem.show();
                    elem.show();
                }
                else {

                    chart.setData(v);
                    chart.setupGrid();
                    chart.draw();
                    overview.setData(v);
                    overview.setupGrid();
                    overview.draw();
                }
            });

            jQuery("#chart").bind("plotselected", function (event, ranges) {

    			// do the zooming
    			jQuery.each(chart.getXAxes(), function(_, axis) {
    				var opts = axis.options;
    				opts.min = ranges.xaxis.from;
    				opts.max = ranges.xaxis.to;
    				zoom(opts.min, opts.max);
    			});
    			chart.setupGrid();
    			chart.draw();
    			chart.clearSelection();

    			// don't fire event on the overview to prevent eternal loop

    			overview.setSelection(ranges, true);
    		});
    		jQuery("#overview").bind("plotselected", function (event, ranges) {
    			chart.setSelection(ranges);
    		});

    		// zoom to the given minimum and maximum millisecond values
    		// update the current data to be a subset between the values
    		function zoom(min, max) {
    			scope.stories = [];
    			angular.forEach(scope.fullStories, function(story, index) {
    				var created = Date.parse(story.fields.created);
    				var resolved = story.fields.resolutiondate !== null ? Date.parse(story.fields.resolutiondate) : null;
    				if (created <= max && (resolved === null || resolved >= min)) {
    					scope.stories.push(story);
    				}
    			});
    			scope.chartMin = min;
    			scope.chartMax = max;
    			// refresh the page, wrap in apply so that page updates
    			scope.$apply(function() {
    				scope.refresh();
    			});
    		}
        }
    };
}

<|endoftext|>


<commit_before>/**
 * Created by yuanbaby on 2017/3/29.
 */
var get_area;
var flag = 0;
/*标志位,判断highcharts绘图Vue点击时间更新的series*/
var get_data;

$(document).on("click", ".dropdown-menu li a", function () {
    get_area = $(this).text().trim();
    /*trim()去除空格*/
    /*获取下拉值*/
    $('#area').val(get_area);
    /*区域选择框赋值*/
    console.log(get_area);
});

var data_fitst = [];

var area_choose = new Vue({
    el: '#area_choose',
    data: {
        items: [
            {message: '新城区'},
            {message: '碑林区'},
            {message: '莲湖区'},
            {message: '雁塔区'},
            {message: '未央区'},
            {message: '灞桥区'},
            {message: '长安区'},
            {message: '阎良区'}
        ]
    }
});
var new_data1 = ['新城区', '碑林区', '莲湖区', '雁塔区', '未央区', '灞桥区', '长安区', '阎良区']
$('#area').typeahead({
    /*输入提示框*/
    source: new_data1,
    items: 7        /*下拉菜单中显示的最大的条目数。*/
})

var json = {};
var options = {
    chart: {
        type: 'column'
    },
    title: {
        text: 'ping时延对比'
    },
    xAxis: {
        categories: ['新城区', '碑林区']
    },
    yAxis: {
        title: {
            text: '结果(ms)'
        }
    },
    credits: {
        enabled: false
    },
    series: [{
        name: '平均时延',
        data: [0, 0]
    }, {
        name: '最大时延',
        data: [0, 0]
    }, {
        name: '最小时延',
        data: [0, 0]
    }
    ]
};
$(document).ready(function () {
    var chart = new Highcharts.Chart('container', options)
});

$('input[name="daterange"]').daterangepicker(

    {
        language:'zn-ch',
        showDropdowns:false,
        applyClass:'btn-success sure',

        locale: {
            format: 'YYYY-MM-DD',               /*时间选择器汉化*/
            applyLabel:'确定',
            cancelLabel:'取消',
            fromLabel:'开始',
            toLabel:'结束',
            monthNames:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
            daysOfWeek:"一_二_三_四_五_六_日".split("_"),

        },
        startDate: '2013-01-01',
        endDate: '2013-12-31'
    },
    function (start, end, label) {          /*日期选择触发事件*/
        console.log("A new date range was chosen: " + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD'));
        console.log("地区选择:"+typeof(get_area) == "undefined");
        if(typeof(get_area) != "undefined"){
        flag = 1;
        /*改变标志位*/
        get_data = {
            /*模拟异步数据*/
            myarea: get_area,
            AverageDelay: 18,
            MaxDelay: 22,
            MinDelay: 17,
            Loss: 0.5,
            Qoe: 98
        };
        options.xAxis = {
            categories: [get_area]    /*图表中更改地区信息*/  /*[]必须要，不然出错*/
        };
        options.series = [{
            name: '平均时延',
            data: [get_data.AverageDelay]      /*[]必须要，不然出错*/
        }, {
            name: '最大时延',
            data: [get_data.MaxDelay]
        }, {
            name: '最小时延',
            data: [get_data.MinDelay]
        }
        ];
        var chart = new Highcharts.Chart('container', options);
        /*重新绘制图表*/

        new_series_delay = [{
            name: '平均时延',
            data: [get_data.AverageDelay]      /*[]必须要，不然出错*/
        }, {
            name: '最大时延',
            data: [get_data.MaxDelay]
        }, {
            name: '最小时延',
            data: [get_data.MinDelay]
        }
        ];

        new_series_loss = [{
            name: '丢包',
            data: [get_data.Loss]
        }
        ];

        new_series_qoe = [{
            name: 'qoe',
            data: [get_data.Qoe]
        }
        ];

        $("#area_table tbody").empty();
        /*清空表*/
        str = "
" + get_data.myarea + "	" + get_data.AverageDelay + "	" + get_data.MaxDelay + "	" + get_data.MinDelay + "	" + get_data.Loss + "	" + get_data.Qoe + "
";
        $("#area_table tbody").append(str);
        }else {          /*如果不选择地区,默认按照日期更新新城区和碑林区的数据*/

            /*********************************************/
            var area1 = {
                myarea: "新城区",
                AverageDelay: 18.666666,
                MaxDelay: 21.2333,
                MinDelay: 17.4,
                Loss: 0.03,
                Qoe: 98.6
            };
            var area2 = {
                myarea: "碑林区",
                AverageDelay: 19.888888,
                MaxDelay: 23.322,
                MinDelay: 18.7,
                Loss: 0.02,
                Qoe: 96.7
            };
            new_area_data = [area1, area2];
            /*页面刚加载,模拟异步数据*/
            /********************************************************/
            new_data.users = new_area_data;        /*观察者,更新highcharts表和表格*/
            console.log(new_data.users);

        }

    });
/*$('#datepicker').datetimepicker({
 minView: "month", //选择日期后，不会再跳转去选择时分秒
 format: "yyyy-mm-dd", //选择日期后，文本框显示的日期格式
 language: 'zh-CN', //汉化
 autoclose:true //选择日期后自动关闭
 });*/

var button_change = new Vue({
    /*实例化Vue*/
    el: '#charts_button',
    data: {
        option_delay: {
            /*设置时延option*/
            title: {
                text: 'ping时延对比'
            },
            series_delay: [{
                name: '平均时延',
                data: [50, 50]
            }, {
                name: '最大时延',
                data: [50, 50]
            }, {
                name: '最小时延',
                data: [50, 50]
            }
            ],
            yAxis: {
                title: {
                    text: '结果(ms)'
                }
            }
        },
        option_qoe: {
            /*设置qoe option*/
            title: {
                text: 'qoe对比'
            },
            series_qoe: [{
                name: 'qoe',
                data: [0, 0]
            }
            ],
            yAxis: {
                title: {
                    text: '结果(分)'
                },
                max: 100
            }
        },
        option_loss: {
            /*设置丢包option*/
            title: {
                text: '丢包率'
            },
            series_loss: [{
                name: '丢包',
                data: [0, 0]
            }
            ],
            yAxis: {
                title: {
                    text: '结果(%)'
                },
                max: 100
            },
            tooltip: {
                /*数据提示框*/
                valueSuffix: '%'    /* y值后缀字符串*/
            }
        }

    },
    // 在 `methods` 对象中定义方法
    methods: {
        /*事件监听*/
        delay: function () {
            console.log("时延");
            options.title = this.option_delay.title;
            /*设置标题*/
            if (flag == 0) {
                options.series = this.option_delay.series_delay;
                /*设置数据*/
            } else {
                options.series = new_series_delay;
                /*series*/
            }
            options.yAxis = this.option_delay.yAxis;
            /*设置y轴*/
            options.tooltip = {};
            /*设置数据提示框*/
            var chart = new Highcharts.Chart('container', options)
            /*重新绘图*/
        },
        loss: function () {
            console.log("丢包");
            options.title = this.option_loss.title;
            if (flag == 0) {
                options.series = this.option_loss.series_loss;
            } else {
                options.series = new_series_loss
            }
            options.yAxis = this.option_loss.yAxis;
            options.tooltip = this.option_loss.tooltip;
            var chart = new Highcharts.Chart('container', options)
        },
        qoe: function () {
            console.log("qoe");
            options.title = this.option_qoe.title;
            if (flag == 0) {
                options.series = this.option_qoe.series_qoe;
            } else {
                options.series = new_series_qoe
            }
            options.yAxis = this.option_qoe.yAxis;
            options.tooltip = {};
            var chart = new Highcharts.Chart('container', options)
        }
    }
});

Vue.component('data-table', {
    template: '

',
    props: ['users'],
    data() {
        return {
            headers: [
                {title: '区县'},
                {title: '平均时延(ms)', class: 'some-special-class'},
                {title: '最大时延(ms)'},
                {title: '最小时延(ms)'},
                {title: '丢包(%)'},
                {title: 'qoe(分)'}
            ],
            rows: [],
            dtHandle: null
        }
    },
    watch: {
        users(val, oldVal) {
            let vm = this;
            vm.rows = [];

            for (var i = 0; i <= 1; i++) {                          /*观察user是否变化,重绘HighCharts图*/
                options.series[0].data[i] = val[i].AverageDelay;
                /*动态设置option*/
                options.series[1].data[i] = val[i].MaxDelay;
                options.series[2].data[i] = val[i].MinDelay;

                button_change.option_delay.series_delay[0].data[i] = val[i].AverageDelay;
                /*动态设置button_change.option*/
                button_change.option_delay.series_delay[1].data[i] = val[i].MaxDelay;
                button_change.option_delay.series_delay[2].data[i] = val[i].MinDelay;
                button_change.option_loss.series_loss[0].data[i] = val[i].Loss;
                button_change.option_qoe.series_qoe[0].data[i] = val[i].Qoe;
            }
            var chart = new Highcharts.Chart('container', options);

            // You should _probably_ check that this is changed data... but we'll skip that for this example.
            val.forEach(function (item) {              /*观察user是否变化,更新表格数据*/
                // Fish out the specific column data for each item in your data set and push it to the appropriate place.
                // Basically we're just building a multi-dimensional array here. If the data is _already_ in the right format you could
                // skip this loop...
                let row = [];

                row.push(item.myarea);
                row.push(item.AverageDelay);
                row.push(item.MaxDelay);
                row.push(item.MinDelay);
                row.push(item.Loss);
                row.push(item.Qoe);

                console.log(item);

                vm.rows.push(row);
            });

            // Here's the magic to keeping the DataTable in sync.
            // It must be cleared, new rows added, then redrawn!
            vm.dtHandle.clear();
            vm.dtHandle.rows.add(vm.rows);
            vm.dtHandle.draw();
        }
    },
    mounted() {
        let vm = this;
        // Instantiate the datatable and store the reference to the instance in our dtHandle element.
        vm.dtHandle = $(this.$el).DataTable({
            // Specify whatever options you want, at a minimum these:
            columns: vm.headers,
            data: vm.rows,
            searching: false,
            paging: false,
            //serverSide: true,
            info: false,
            ordering:false,    /*禁用排序功能*/
            /*bInfo: false,*/
            bLengthChange: false,    /*禁用Show entries*/
            dom: 'Bfrtip',
            buttons: [
                'copy', 'excel', 'pdf'
            ]
        });

        /*new $.fn.dataTable.Buttons( vm.dtHandle, {
            buttons: [
                'copy', 'excel', 'pdf'
            ]
        } );*/
    }
});

var new_data = new Vue({
    el: '#tabledemo',
    data: {
        users: [],
        search: ''
    },
    computed: {
        filteredUsers: function () {                 /*此处可以对传入数据进行处理*/
            let self = this;
            return self.users;
            /*let search = self.search.toLowerCase();
             return self.users.filter(function (user) {
             return user.username.toLowerCase().indexOf(search) !== -1 ||
             user.email.toLowerCase().indexOf(search) !== -1 ||
             user.mobile.indexOf(search) !== -1
             })*/
        }
    },
    mounted() {
        let vm = this;
        /*********************************************/
        var area1 = {
            myarea: "新城区",
            AverageDelay: 18,
            MaxDelay: 21,
            MinDelay: 17,
            Loss: 0.03,
            Qoe: 98
        };
        var area2 = {
            myarea: "碑林区",
            AverageDelay: 19,
            MaxDelay: 23,
            MinDelay: 18,
            Loss: 0.02,
            Qoe: 96
        };
        data_fitst = [area1, area2];
        /*页面刚加载,模拟异步数据*/
        /********************************************************/

        vm.users = data_fitst;
        console.log(vm.users);

        /*$.ajax({
         url: '../sys/user/list',
         dataType: 'json',
         data: {
         username: null,
         page: 1,
         limit: 10
         },
         success(r) {
         vm.users = r.page.list;
         console.log(vm.users)
         }
         });*/
    }
});

       /*导出表格到excel*/
function exportExcel() {
    alasql('SELECT * INTO XLSX("区县Ping对比.xlsx",{headers:true}) \
                    FROM HTML("#area_table",{headers:true})');

}

/*$(document).ready(function() {
    alasql('SELECT * INTO HTML("#res",{headers:true}) \
                  FROM XLSX("C:/Users/yuanbaby/Downloads/Ping.xlsx",\
                            {headers:true})');
    alert("end of function")
});*/

<commit_msg>2017年3月31日19:42:57 highcharts和表格更新全由watch负责<commit_after>/**
 * Created by yuanbaby on 2017/3/29.
 */
var get_area;
var flag = 0;
/*标志位,判断highcharts绘图Vue点击时间更新的series*/
var get_data;

$(document).on("click", ".dropdown-menu li a", function () {
    get_area = $(this).text().trim();
    /*trim()去除空格*/
    /*获取下拉值*/
    $('#area').val(get_area);
    /*区域选择框赋值*/
    console.log(get_area);
});

var data_fitst = [];

var area_choose = new Vue({
    el: '#area_choose',
    data: {
        items: [
            {message: '新城区'},
            {message: '碑林区'},
            {message: '莲湖区'},
            {message: '雁塔区'},
            {message: '未央区'},
            {message: '灞桥区'},
            {message: '长安区'},
            {message: '阎良区'}
        ]
    }
});
var new_data1 = ['新城区', '碑林区', '莲湖区', '雁塔区', '未央区', '灞桥区', '长安区', '阎良区']
$('#area').typeahead({
    /*输入提示框*/
    source: new_data1,
    items: 7        /*下拉菜单中显示的最大的条目数。*/
})

var json = {};
var options = {
    chart: {
        type: 'column'
    },
    title: {
        text: 'ping时延对比'
    },
    xAxis: {
        categories: []
    },
    yAxis: {
        title: {
            text: '结果(ms)'
        }
    },
    credits: {
        enabled: false
    },
    series: [{
        name: '平均时延',
        data: []
    }, {
        name: '最大时延',
        data: []
    }, {
        name: '最小时延',
        data: []
    }
    ]
};
$(document).ready(function () {
    var chart = new Highcharts.Chart('container', options)
});

$('input[name="daterange"]').daterangepicker(

    {
        language:'zn-ch',
        showDropdowns:false,
        applyClass:'btn-success sure',

        locale: {
            format: 'YYYY-MM-DD',               /*时间选择器汉化*/
            applyLabel:'确定',
            cancelLabel:'取消',
            fromLabel:'开始',
            toLabel:'结束',
            monthNames:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
            daysOfWeek:"一_二_三_四_五_六_日".split("_"),

        },
        startDate: '2013-01-01',
        endDate: '2013-12-31'
    },
    function (start, end, label) {          /*日期选择触发事件*/
        console.log("A new date range was chosen: " + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD'));
        console.log("地区选择:"+typeof(get_area) == "undefined");
        if(typeof(get_area) != "undefined"){
        flag = 1;
        /*改变标志位*/
        get_data = {
            /*模拟异步数据*/
            myarea: get_area,
            AverageDelay: 18,
            MaxDelay: 22,
            MinDelay: 17,
            Loss: 0.5,
            Qoe: 98
        };
            new_data.users = [get_data];     /*更新user数据*/
        }else {          /*如果不选择地区,默认按照日期更新新城区和碑林区的数据*/

            /*********************************************/
            var area1 = {
                myarea: "新城区",
                AverageDelay: 18.666666,
                MaxDelay: 21.2333,
                MinDelay: 17.4,
                Loss: 0.03,
                Qoe: 98.6
            };
            var area2 = {
                myarea: "碑林区",
                AverageDelay: 19.888888,
                MaxDelay: 23.322,
                MinDelay: 18.7,
                Loss: 0.02,
                Qoe: 96.7
            };
            new_area_data = [area1, area2];
            /*页面刚加载,模拟异步数据*/
            /********************************************************/
            new_data.users = new_area_data;        /*观察者,更新highcharts表和表格*/
            console.log(new_data.users);

        }

    });
/*$('#datepicker').datetimepicker({
 minView: "month", //选择日期后，不会再跳转去选择时分秒
 format: "yyyy-mm-dd", //选择日期后，文本框显示的日期格式
 language: 'zh-CN', //汉化
 autoclose:true //选择日期后自动关闭
 });*/

var button_change = new Vue({
    /*实例化Vue*/
    el: '#charts_button',
    data: {
        option_delay: {
            /*设置时延option*/
            title: {
                text: 'ping时延对比'
            },
            series_delay: [{
                name: '平均时延',
                data: []
            }, {
                name: '最大时延',
                data: []
            }, {
                name: '最小时延',
                data: []
            }
            ],
            yAxis: {
                title: {
                    text: '结果(ms)'
                }
            }
        },
        option_qoe: {
            /*设置qoe option*/
            title: {
                text: 'qoe对比'
            },
            series_qoe: [{
                name: 'qoe',
                data: []
            }
            ],
            yAxis: {
                title: {
                    text: '结果(分)'
                },
                max: 100
            }
        },
        option_loss: {
            /*设置丢包option*/
            title: {
                text: '丢包率'
            },
            series_loss: [{
                name: '丢包',
                data: []
            }
            ],
            yAxis: {
                title: {
                    text: '结果(%)'
                },
                max: 100
            },
            tooltip: {
                /*数据提示框*/
                valueSuffix: '%'    /* y值后缀字符串*/
            }
        }

    },
    // 在 `methods` 对象中定义方法
    methods: {
        /*事件监听*/
        delay: function () {
            console.log("时延");
            options.title = this.option_delay.title;
            /*设置标题*/

            options.series = this.option_delay.series_delay;
            /*设置数据*/

            options.yAxis = this.option_delay.yAxis;
            /*设置y轴*/
            options.tooltip = {};
            /*设置数据提示框*/
            var chart = new Highcharts.Chart('container', options)
            /*重新绘图*/
        },
        loss: function () {
            console.log("丢包");
            options.title = this.option_loss.title;

            options.series = this.option_loss.series_loss;

            options.yAxis = this.option_loss.yAxis;
            options.tooltip = this.option_loss.tooltip;
            var chart = new Highcharts.Chart('container', options)
        },
        qoe: function () {
            console.log("qoe");
            options.title = this.option_qoe.title;

            options.series = this.option_qoe.series_qoe;

            options.yAxis = this.option_qoe.yAxis;
            options.tooltip = {};
            var chart = new Highcharts.Chart('container', options)
        }
    }
});

Vue.component('data-table', {
    template: '

',
    props: ['users'],
    data() {
        return {
            headers: [
                {title: '区县'},
                {title: '平均时延(ms)', class: 'some-special-class'},
                {title: '最大时延(ms)'},
                {title: '最小时延(ms)'},
                {title: '丢包(%)'},
                {title: 'qoe(分)'}
            ],
            rows: [],
            dtHandle: null
        }
    },
    watch: {
        users(val, oldVal) {
            let vm = this;
            vm.rows = [];
            var times = 1;
            if(flag==1){
                times=0;                          /*先清空所有option的data*/
                options.xAxis.categories=[];
                options.series[0].data=[];
                /*动态设置option*/
                options.series[1].data=[];
                options.series[2].data=[];

                button_change.option_delay.series_delay[0].data=[];
                /*动态设置button_change.option*/
                button_change.option_delay.series_delay[1].data=[];
                button_change.option_delay.series_delay[2].data=[];
                button_change.option_loss.series_loss[0].data=[];
                button_change.option_qoe.series_qoe[0].data=[];
            }

            for (var i = 0; i <= times; i++) {                          /*观察user是否变化,重绘HighCharts图*/
                options.xAxis.categories[i] = val[i].myarea;
                options.series[0].data[i] = val[i].AverageDelay;
                /*动态设置option*/
                options.series[1].data[i] = val[i].MaxDelay;
                options.series[2].data[i] = val[i].MinDelay;

                button_change.option_delay.series_delay[0].data[i] = val[i].AverageDelay;
                /*动态设置button_change.option*/
                button_change.option_delay.series_delay[1].data[i] = val[i].MaxDelay;
                button_change.option_delay.series_delay[2].data[i] = val[i].MinDelay;
                button_change.option_loss.series_loss[0].data[i] = val[i].Loss;
                button_change.option_qoe.series_qoe[0].data[i] = val[i].Qoe;
            }
            var chart = new Highcharts.Chart('container', options);

            // You should _probably_ check that this is changed data... but we'll skip that for this example.
            val.forEach(function (item) {              /*观察user是否变化,更新表格数据*/
                // Fish out the specific column data for each item in your data set and push it to the appropriate place.
                // Basically we're just building a multi-dimensional array here. If the data is _already_ in the right format you could
                // skip this loop...
                let row = [];

                row.push(item.myarea);
                row.push(item.AverageDelay);
                row.push(item.MaxDelay);
                row.push(item.MinDelay);
                row.push(item.Loss);
                row.push(item.Qoe);

                console.log(item);

                vm.rows.push(row);
            });

            // Here's the magic to keeping the DataTable in sync.
            // It must be cleared, new rows added, then redrawn!
            vm.dtHandle.clear();
            vm.dtHandle.rows.add(vm.rows);
            vm.dtHandle.draw();
        }
    },
    mounted() {
        let vm = this;
        // Instantiate the datatable and store the reference to the instance in our dtHandle element.
        vm.dtHandle = $(this.$el).DataTable({
            // Specify whatever options you want, at a minimum these:
            columns: vm.headers,
            data: vm.rows,
            searching: false,
            paging: false,
            //serverSide: true,
            info: false,
            ordering:false,    /*禁用排序功能*/
            /*bInfo: false,*/
            bLengthChange: false,    /*禁用Show entries*/
            dom: 'Bfrtip',
            buttons: [
                'copy', 'excel', 'pdf'
            ]
        });

        /*new $.fn.dataTable.Buttons( vm.dtHandle, {
            buttons: [
                'copy', 'excel', 'pdf'
            ]
        } );*/
    }
});

var new_data = new Vue({
    el: '#tabledemo',
    data: {
        users: [],
        search: ''
    },
    computed: {
        filteredUsers: function () {                 /*此处可以对传入数据进行处理*/
            let self = this;
            return self.users;
            /*let search = self.search.toLowerCase();
             return self.users.filter(function (user) {
             return user.username.toLowerCase().indexOf(search) !== -1 ||
             user.email.toLowerCase().indexOf(search) !== -1 ||
             user.mobile.indexOf(search) !== -1
             })*/
        }
    },
    mounted() {
        let vm = this;
        /*********************************************/
        var area1 = {
            myarea: "新城区",
            AverageDelay: 18,
            MaxDelay: 21,
            MinDelay: 17,
            Loss: 0.03,
            Qoe: 98
        };
        var area2 = {
            myarea: "碑林区",
            AverageDelay: 19,
            MaxDelay: 23,
            MinDelay: 18,
            Loss: 0.02,
            Qoe: 96
        };
        data_fitst = [area1, area2];
        /*页面刚加载,模拟异步数据*/
        /********************************************************/

        vm.users = data_fitst;
        console.log(vm.users);

        /*$.ajax({
         url: '../sys/user/list',
         dataType: 'json',
         data: {
         username: null,
         page: 1,
         limit: 10
         },
         success(r) {
         vm.users = r.page.list;
         console.log(vm.users)
         }
         });*/
    }
});

       /*导出表格到excel*/
function exportExcel() {
    alasql('SELECT * INTO XLSX("区县Ping对比.xlsx",{headers:true}) \
                    FROM HTML("#area_table",{headers:true})');

}

/*$(document).ready(function() {
    alasql('SELECT * INTO HTML("#res",{headers:true}) \
                  FROM XLSX("C:/Users/yuanbaby/Downloads/Ping.xlsx",\
                            {headers:true})');
    alert("end of function")
});*/

<|endoftext|>