<commit_before>/*
 * (C) Copyright 2014 Mock Service Layer Contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/**
 **
 ** Test Library to be used in conjunction with web-server.js
 **
 **/

/**
 * Method to register mock response. Once you register, whenever server receives a request matching
 * the registered requestPath, it will respond with a fake response
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param body => Json object that contains the requestPath, contentType, responseText, delayTime, headers, function.
 **/
setMockRespond = function(server, port, body)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/fakerespond", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to register a template to be used when mocking responses. Once registered, pass the same id
 * used to register the template along with a map containing the key-value pairs that are to be replaced.
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param template => a template in the form of a string
 * @param id => the id to be used as a key for the template which is used when setting a fake response
 *
 **/
registerTemplate = function(server, port, template, id)
{
	var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.template= template;
    body.id = id;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/template", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');

    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to register intercept XHR. Once you register, whenever server receives a request matching
 * the registered requestPath, it will intercept and store for later retrieval
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param requestPath => path which you want to intercept.
 *
 **/
setInterceptXHR = function(server, port, requestPath)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= requestPath;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/interceptxhr", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');

    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to retrieve intercepted XHRs. Use in conjunction with setInterceptXHR()
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param requestPath => path which you have intercepted.
 * @param callback => method to call to validate. responseText will be provided to callback
 *                    responseText is an object containing the following:
 *                          {xhr_1={obj1, obj2..}, xhr_2={obj1, obj2..}...}
 *                              where obj#={xhr,post}.
 *                              xhr will have url obj, method type, and body
 *
 **/
getInterceptedXHR = function(server, port, requestPath)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= requestPath;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/getinterceptedxhr", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.onreadystatechange = function() {
        if (xmlHttp.readyState == 4 && xmlHttp.status==200) {
            return JSON.parse(xmlHttp.responseText);
        }
    }

    xmlHttp.send(JSON.stringify(body));

}

/**
 * Method to set up parameters that will be ignored in the URL.
 *  *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param params => parameters that will be ignored in the app URL, type is string.
 *                  For example,if we set ignore paramB, URL http://aa.bb.com/result?paramA=123&paramB=456 will be treated as http://aa.bb.com/result?paramA=123
 **/
setParamIgnored = function(server, port, params)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= params;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/setIgnoreFlag", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to delete registered mock response.
 *  *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param requestPath => mock response path that needs to be deleted, if empty then delete all the registered mock responses.
 **/
unRegisterMock = function(server, port, requestPath)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= requestPath;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/unregisterMock", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.send(JSON.stringify(body));
}<commit_msg>Fix for issue #15<commit_after>/*
 * (C) Copyright 2014 Mock Service Layer Contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/**
 **
 ** Test Library to be used in conjunction with web-server.js
 **
 **/

/**
 * Method to register mock response. Once you register, whenever server receives a request matching
 * the registered requestPath, it will respond with a fake response
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param body => Json object that contains the requestPath, contentType, responseText, delayTime, headers, function.
 **/
setMockRespond = function(server, port, body)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/fakerespond", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to register a template to be used when mocking responses. Once registered, pass the same id
 * used to register the template along with a map containing the key-value pairs that are to be replaced.
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param template => a template in the form of a string
 * @param id => the id to be used as a key for the template which is used when setting a fake response
 *
 **/
registerTemplate = function(server, port, template, id)
{
	var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.template= template;
    body.id = id;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/template", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');

    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to register intercept XHR. Once you register, whenever server receives a request matching
 * the registered requestPath, it will intercept and store for later retrieval
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param requestPath => path which you want to intercept.
 *
 **/
setInterceptXHR = function(server, port, requestPath)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= requestPath;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/interceptxhr", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');

    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to retrieve intercepted XHRs. Use in conjunction with setInterceptXHR()
 *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param requestPath => path which you have intercepted.
 * @param callback => method to call to validate. responseText will be provided to callback
 *                    responseText is an object containing the following:
 *                          {xhr_1={obj1, obj2..}, xhr_2={obj1, obj2..}...}
 *                              where obj#={xhr,post}.
 *                              xhr will have url obj, method type, and body
 *
 **/
getInterceptedXHR = function(server, port, requestPath, callback)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= requestPath;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/mock/getinterceptedxhr", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.onreadystatechange = function() {
        if (xmlHttp.readyState == 4 && xmlHttp.status==200) {
            callback(xmlHttp.responseText);
        }
    }

    xmlHttp.send(JSON.stringify(body));

}

/**
 * Method to set up parameters that will be ignored in the URL.
 *  *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param params => parameters that will be ignored in the app URL, type is string.
 *                  For example,if we set ignore paramB, URL http://aa.bb.com/result?paramA=123&paramB=456 will be treated as http://aa.bb.com/result?paramA=123
 **/
setParamIgnored = function(server, port, params)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= params;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/setIgnoreFlag", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.send(JSON.stringify(body));
}

/**
 * Method to delete registered mock response.
 *  *
 * @param server => url of web-server.js running on node
 * @param port => port number of web-server.js running on node
 * @param requestPath => mock response path that needs to be deleted, if empty then delete all the registered mock responses.
 **/
unRegisterMock = function(server, port, requestPath)
{
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();

	var body = {};
    body.requestPath= requestPath;

    xmlHttp.open( "POST", "http://" + server + ":" + port + "/unregisterMock", true );
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    xmlHttp.send(JSON.stringify(body));
}
<|endoftext|>


<commit_before>import axios from 'axios';
import { mount } from '@vue/test-utils';
import { createLocalVue } from './helper';

import Vuex from 'vuex';

import advisers from '../vuex/store/advisers';
import profile from '../vuex/store/profile';
import javgAdvisers from '../tests/mock_data/advisers/javerage.json';
import javgProfile from '../tests/mock_data/profile/javerage.json';

import AssignedAdviserCard from '../components/academics/adviser.vue';
import UwCard from '../components/_templates/card.vue';

const localVue = createLocalVue(Vuex);
jest.mock('axios');
localVue.component('uw-card', UwCard);

describe('Assigned Adviser Card', () => {
  let store;

  beforeEach(() => {
    store = new Vuex.Store({
      modules: {
        advisers,
        profile,
      },
      state: {
        user: {
          affiliations: {
            undergrad: true,
          }
        }
      }
    });
  });

  it('Show Assigned Adviser card for undergrad (javerage)', async () => {
    axios.get.mockImplementation((url) => {
      const urlData = {
        '/api/v1/advisers/': javgAdvisers,
        '/api/v1/profile/': javgProfile,
      };
      return Promise.resolve({data: urlData[url]});
    });
    const wrapper = mount(AssignedAdviserCard, {store, localVue});
    await new Promise(setImmediate);

    expect(wrapper.findComponent(UwCard).exists()).toBe(true);
    expect(wrapper.vm.showCard).toBe(true);
    expect(wrapper.vm.isUndergrad).toBe(true);
    expect(wrapper.vm.advisers.length).toBe(5);
  });

  it('Hide Assigned Adviser card if not undergrad', async () => {
    store.state.user.affiliations.undergrad = false;
    const wrapper = mount(AssignedAdviserCard, {store, localVue});
    await new Promise(setImmediate);
    expect(wrapper.vm.showCard).toBe(false);
  });

  it('Show error', async () => {
    axios.get.mockImplementation((url) => {
      return Promise.reject({response: {status: 543}});
    });
    const wrapper = mount(AssignedAdviserCard, {store, localVue});
    await new Promise(setImmediate);
    expect(wrapper.vm.showCard).toBe(true);
    expect(wrapper.vm.showError).toBe(true);
  });

  it('Hide error', async () => {
    axios.get.mockImplementation((url) => {
      return Promise.reject({response: {status: 404}});
    });
    const wrapper = mount(AssignedAdviserCard, {store, localVue,});
    await new Promise(setImmediate);
    expect(wrapper.vm.showCard).toBe(true);
    expect(wrapper.vm.showError).toBe(false);
  });
});<commit_msg>add test of sorting result<commit_after>import axios from 'axios';
import { mount } from '@vue/test-utils';
import { createLocalVue } from './helper';

import Vuex from 'vuex';

import advisers from '../vuex/store/advisers';
import profile from '../vuex/store/profile';
import javgAdvisers from '../tests/mock_data/advisers/javerage.json';
import javgProfile from '../tests/mock_data/profile/javerage.json';

import AssignedAdviserCard from '../components/academics/adviser.vue';
import UwCard from '../components/_templates/card.vue';

const localVue = createLocalVue(Vuex);
jest.mock('axios');
localVue.component('uw-card', UwCard);

describe('Assigned Adviser Card', () => {
  let store;

  beforeEach(() => {
    store = new Vuex.Store({
      modules: {
        advisers,
        profile,
      },
      state: {
        user: {
          affiliations: {
            undergrad: true,
          }
        }
      }
    });
  });

  it('Show Assigned Adviser card for undergrad (javerage)', async () => {
    axios.get.mockImplementation((url) => {
      const urlData = {
        '/api/v1/advisers/': javgAdvisers,
        '/api/v1/profile/': javgProfile,
      };
      return Promise.resolve({data: urlData[url]});
    });
    const wrapper = mount(AssignedAdviserCard, {store, localVue});
    await new Promise(setImmediate);

    expect(wrapper.findComponent(UwCard).exists()).toBe(true);
    expect(wrapper.vm.showCard).toBe(true);
    expect(wrapper.vm.isUndergrad).toBe(true);
    const advisers = wrapper.vm.advisers;
    expect(advisers.length).toBe(5);
    expect(advisers[0].program).toBe("UAA Advising");
    expect(advisers[1].program).toBe("OMAD Advising");
    expect(advisers[2].program).toBe("UW Honors");
    expect(advisers[3].program).toBe("Robinson Center");
    expect(advisers[4].program).toBe("Athletics – SAAS");
  });

  it('Hide Assigned Adviser card if not undergrad', async () => {
    store.state.user.affiliations.undergrad = false;
    const wrapper = mount(AssignedAdviserCard, {store, localVue});
    await new Promise(setImmediate);
    expect(wrapper.vm.showCard).toBe(false);
  });

  it('Show error', async () => {
    axios.get.mockImplementation((url) => {
      return Promise.reject({response: {status: 543}});
    });
    const wrapper = mount(AssignedAdviserCard, {store, localVue});
    await new Promise(setImmediate);
    expect(wrapper.vm.showCard).toBe(true);
    expect(wrapper.vm.showError).toBe(true);
  });

  it('Hide error', async () => {
    axios.get.mockImplementation((url) => {
      return Promise.reject({response: {status: 404}});
    });
    const wrapper = mount(AssignedAdviserCard, {store, localVue,});
    await new Promise(setImmediate);
    expect(wrapper.vm.showCard).toBe(true);
    expect(wrapper.vm.showError).toBe(false);
  });
});<|endoftext|>


<commit_before>/**
 * @fileoverview Implement 'currentTransform' of CanvasRenderingContext2D prototype (polyfill)
 * @author Stefan Goessner (c) 2015
 */

/**
 * extend CanvasRenderingContext2D.prototype by current transformation matrix access.
 */
if (!("currentTransform" in CanvasRenderingContext2D.prototype)) {
/**
 * define property 'currentTransform'
 */
   if ("mozCurrentTransform" in CanvasRenderingContext2D.prototype) {
      Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", {
         get : function() { var m = this.mozCurrentTransform; return {a:m[0],b:m[1],c:m[2],d:m[3],e:m[4],f:m[5]}; },
         set : function(x) { this.mozCurrentTransform = [x.a,x.b,x.c,x.d,x.e,x.f]; },
         enumerable : true,
         configurable : false
      });
   }
   else if ("webkitCurrentTransform" in CanvasRenderingContext2D.prototype) {
      Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", {
         get : function() { return this.webkitCurrentTransform; },
         set : function(x) { this.webkitCurrentTransform = x; },
         enumerable : true,
         configurable : false
      });
   }
   else {  // fully implement it ... hmm ... 'currentTransform', 'save()', 'restore()', 'transform()', 'setTransform()', 'resetTransform()'
      Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", {
         get : function() { return this._t2stack && this._t2stack[this._t2stack.length-1] || {a:1,b:0,c:0,d:1,e:0,f:0}; },
         set : function(x) {
            if (!this._t2stack)
               this._t2stack = [{}];
            this._t2stack[this._t2stack.length-1] = {a:x.a,b:x.b,c:x.c,d:x.d,e:x.e,f:x.f};
         },
         enumerable : true,
         configurable : false
      });
      CanvasRenderingContext2D.prototype.save = function() {
         var save = CanvasRenderingContext2D.prototype.save;
         return function() {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];
            this._t2stack.push(t && {a:t.a,b:t.b,c:t.c,d:t.d,e:t.e,f:t.f});
            save.call(this);
         }
      }();
      CanvasRenderingContext2D.prototype.restore = function() {
         var restore = CanvasRenderingContext2D.prototype.restore;
         return function() {
            if (this._t2stack) this._t2stack.pop();
            restore.call(this);
         }
      }();
      CanvasRenderingContext2D.prototype.transform = function() {
         var transform = CanvasRenderingContext2D.prototype.transform;
         return function(a,b,c,d,e,f) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1], q;

            var na = t.a*a + t.c * b;
            var nb = t.b*a + t.d * b;

            var nc = t.a*c + t.c * d;
            var nd = t.b*c + t.d * d;

            var ne = t.e + t.a*e + t.c*f;
            var nf = t.f + t.b*e + t.d*f;

            t.a = na;
            t.b = nb;
            t.c = nc;
            t.d = nd;
            t.e = ne;
            t.f = nf;
            transform.call(this,a,b,c,d,e,f);
         }
      }();
      CanvasRenderingContext2D.prototype.setTransform = function() {
         var setTransform = CanvasRenderingContext2D.prototype.setTransform;
         return function(a,b,c,d,e,f) {
            if (!this._t2stack)
               this._t2stack = [{}];
            this._t2stack[this._t2stack.length-1] = {a:a,b:b,c:c,d:d,e:e,f:f};
            setTransform.call(this,a,b,c,d,e,f);
         }
      }();
      CanvasRenderingContext2D.prototype.resetTransform = function() {
         var resetTransform = CanvasRenderingContext2D.prototype.resetTransform;
         return function() {
            if (!this._t2stack)
               this._t2stack = [{}];
            this._t2stack[this._t2stack.length-1] = {a:1,b:0,c:0,d:1,e:0,f:0};
            resetTransform && resetTransform.call(this);
         }
      }();
      CanvasRenderingContext2D.prototype.scale = function() {
         var scale = CanvasRenderingContext2D.prototype.scale;
         return function(sx,sy) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];
            sx = sx || 1;
            sy = sy || sx;
            t.a *= sx; t.c *= sx;
            t.b *= sy; t.d *= sy;
            scale.call(this,sx,sy);
         }
      }();
      CanvasRenderingContext2D.prototype.rotate = function() {
         var rotate = CanvasRenderingContext2D.prototype.rotate;
         return function(w) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];

            var cw = Math.cos(-w);
            var sw = Math.sin(-w);

            var a = t.a*cw - t.c*sw;
            var b = t.b*cw - t.d*sw;
            var c = t.c*cw + t.a*sw;
            var d = t.d*cw + t.b*sw;

            t.a = a;
            t.b = b;
            t.c = c;
            t.d = d;

            return rotate.call(this,w);
         }
      }();
      CanvasRenderingContext2D.prototype.translate = function() {
         var translate = CanvasRenderingContext2D.prototype.translate;
         return function(x,y) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];
            t.e += x*t.a + y*t.c;
            t.f += x*t.b + y*t.d;
            return translate.call(this,x,y);
         }
      }();
   }
}
<commit_msg>finally fix scale<commit_after>/**
 * @fileoverview Implement 'currentTransform' of CanvasRenderingContext2D prototype (polyfill)
 * @author Stefan Goessner (c) 2015
 */

/**
 * extend CanvasRenderingContext2D.prototype by current transformation matrix access.
 */
if (!("currentTransform" in CanvasRenderingContext2D.prototype)) {
/**
 * define property 'currentTransform'
 */
   if ("mozCurrentTransform" in CanvasRenderingContext2D.prototype) {
      Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", {
         get : function() { var m = this.mozCurrentTransform; return {a:m[0],b:m[1],c:m[2],d:m[3],e:m[4],f:m[5]}; },
         set : function(x) { this.mozCurrentTransform = [x.a,x.b,x.c,x.d,x.e,x.f]; },
         enumerable : true,
         configurable : false
      });
   }
   else if ("webkitCurrentTransform" in CanvasRenderingContext2D.prototype) {
      Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", {
         get : function() { return this.webkitCurrentTransform; },
         set : function(x) { this.webkitCurrentTransform = x; },
         enumerable : true,
         configurable : false
      });
   }
   else {  // fully implement it ... hmm ... 'currentTransform', 'save()', 'restore()', 'transform()', 'setTransform()', 'resetTransform()'
      Object.defineProperty(CanvasRenderingContext2D.prototype, "currentTransform", {
         get : function() {return this._t2stack && this._t2stack[this._t2stack.length-1] || {a:1,b:0,c:0,d:1,e:0,f:0};},
         set : function(x) {
            if (!this._t2stack)
               this._t2stack = [{}];
            this._t2stack[this._t2stack.length-1] = {a:x.a,b:x.b,c:x.c,d:x.d,e:x.e,f:x.f};
         },
         enumerable : true,
         configurable : false
      });
      CanvasRenderingContext2D.prototype.save = function() {
         var save = CanvasRenderingContext2D.prototype.save;
         return function() {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];
            this._t2stack.push(t && {a:t.a,b:t.b,c:t.c,d:t.d,e:t.e,f:t.f});
            save.call(this);
         }
      }();
      CanvasRenderingContext2D.prototype.restore = function() {
         var restore = CanvasRenderingContext2D.prototype.restore;
         return function() {
            if (this._t2stack) this._t2stack.pop();
            restore.call(this);
         }
      }();
      CanvasRenderingContext2D.prototype.transform = function() {
         var transform = CanvasRenderingContext2D.prototype.transform;
         return function(a,b,c,d,e,f) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1], q;

            var na = t.a*a + t.c * b;
            var nb = t.b*a + t.d * b;

            var nc = t.a*c + t.c * d;
            var nd = t.b*c + t.d * d;

            var ne = t.e + t.a*e + t.c*f;
            var nf = t.f + t.b*e + t.d*f;

            t.a = na;
            t.b = nb;
            t.c = nc;
            t.d = nd;
            t.e = ne;
            t.f = nf;
            transform.call(this,a,b,c,d,e,f);
         }
      }();
      CanvasRenderingContext2D.prototype.setTransform = function() {
         var setTransform = CanvasRenderingContext2D.prototype.setTransform;
         return function(a,b,c,d,e,f) {
            if (!this._t2stack)
               this._t2stack = [{}];
            this._t2stack[this._t2stack.length-1] = {a:a,b:b,c:c,d:d,e:e,f:f};
            setTransform.call(this,a,b,c,d,e,f);
         }
      }();
      CanvasRenderingContext2D.prototype.resetTransform = function() {
         var resetTransform = CanvasRenderingContext2D.prototype.resetTransform;
         return function() {
            if (!this._t2stack)
               this._t2stack = [{}];
            this._t2stack[this._t2stack.length-1] = {a:1,b:0,c:0,d:1,e:0,f:0};
            resetTransform && resetTransform.call(this);
         }
      }();
      CanvasRenderingContext2D.prototype.scale = function() {
         var scale = CanvasRenderingContext2D.prototype.scale;
         return function(sx,sy) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];
            sx = sx || 1;
            sy = sy || sx;
            t.a *= sx; t.c *= sy;
            t.b *= sx; t.d *= sy;
            scale.call(this,sx,sy);
         }
      }();
      CanvasRenderingContext2D.prototype.rotate = function() {
         var rotate = CanvasRenderingContext2D.prototype.rotate;
         return function(w) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];

            var cw = Math.cos(-w);
            var sw = Math.sin(-w);

            var a = t.a*cw - t.c*sw;
            var b = t.b*cw - t.d*sw;
            var c = t.c*cw + t.a*sw;
            var d = t.d*cw + t.b*sw;

            t.a = a;
            t.b = b;
            t.c = c;
            t.d = d;

            return rotate.call(this,w);
         }
      }();
      CanvasRenderingContext2D.prototype.translate = function() {
         var translate = CanvasRenderingContext2D.prototype.translate;
         return function(x,y) {
            if (!this._t2stack)
               this._t2stack = [{a:1,b:0,c:0,d:1,e:0,f:0}];
            var t = this._t2stack[this._t2stack.length-1];
            t.e += x*t.a + y*t.c;
            t.f += x*t.b + y*t.d;
            return translate.call(this,x,y);
         }
      }();
   }
}
<|endoftext|>


<commit_before>var http = require('http')
   ,INTERVAL = 10 * 60 * 1000
	 ,SORT_INTERVAL = 1 * 60 * 1000;

var requestOptions = {
  host: 'api.twitter.com',
  port: 80,
  path: '/1/trends.json',
	headers: {
		'User-Agent': "wompt.com"
	}
};

function TwitterTopics(channels){
	this.topics = [];
	this.list = [];
	this.channelManager = channels;

	this._twitter_timer = setInterval(this.updateTopicList.bind(this), INTERVAL);
	this._sort_timer = setInterval(this._sortList.bind(this), SORT_INTERVAL);

	this.updateTopicList();
}

TwitterTopics.prototype.updateTopicList = function(){
	var me = this;
	var req =	http.get(requestOptions, function(res) {
		res.setEncoding('utf8');

		if(res.statusCode == 200){
			var body=[];
			res.on('data', function(data){
				body.push(data);
			}).on('end', function(){
				me._processBody(body.join());
			});
		}

	});
}

TwitterTopics.prototype._processBody = function(body){
	try{
		this.lastResult = JSON.parse(body);
	}catch(e){
		console.log('Error parsing JSON response from Twitter:');
		console.dir(e);
		return;
	}

	var trends = this.lastResult.trends;
	if(trends){
		this.list = trends.map(function(trend){
			return trend.name;
		});

		this._sortList();
		this.lastUpdatedAt = new Date();
	}
}

TwitterTopics.prototype._sortList = function(){
	var me = this;
	if(!this.list) return;
	this.sortedList = this.list.map(function(trend){
		var channel = me.channelManager.peek(trend.replace('#',''));
		return {
			 name: trend
			,channel: channel
			,clients: channel ? channel.clients.userCount : 0
		};
	}).sort(function(a,b){
		return b.clients - a.clients;
	});
}

module.exports = TwitterTopics;
<commit_msg>Changed Twitter API, making it a little more robust<commit_after>var http = require('http')
   ,INTERVAL = 10 * 60 * 1000
	 ,SORT_INTERVAL = 1 * 60 * 1000;

var requestOptions = {
  host: 'api.twitter.com',
  port: 80,
  path: '/1/trends.json',
	headers: {
		'User-Agent': "wompt.com"
	}
};

function TwitterTopics(channels){
	this.list = this.sortedList = [];
	this.channelManager = channels;

	this._twitter_timer = setInterval(this.updateTopicList.bind(this), INTERVAL);
	this._sort_timer = setInterval(this._sortList.bind(this), SORT_INTERVAL);

	this.updateTopicList();
}

TwitterTopics.prototype.updateTopicList = function(){
	var me = this;
	var req =	http.get(requestOptions, function(res) {
		res.setEncoding('utf8');

		if(res.statusCode == 200){
			var body=[];
			res.on('data', function(data){
				body.push(data);
			}).on('end', function(){
				me._processBody(body.join());
			});
		}

	});
}

TwitterTopics.prototype._processBody = function(body){
	try{
		this.lastResult = JSON.parse(body);
	}catch(e){
		console.log('Error parsing JSON response from Twitter:');
		console.dir(e);
		return;
	}

	var trends = this.lastResult.trends;
	if(trends){
		this.list = trends.map(function(trend){
			return trend.name;
		});

		this._sortList();
		this.lastUpdatedAt = new Date();
	}
}

TwitterTopics.prototype._sortList = function(){
	var me = this;
	if(!this.list) return;
	this.sortedList = this.list.filter(function(str){
		return str && str.length > 0;
	})
	.map(function(trend){
		var channel = me.channelManager.peek(trend.replace('#',''));
		return {
			 name: trend
			,channel: channel
			,clients: channel ? channel.clients.userCount : 0
		};
	})
	.sort(function(a,b){
		return b.clients - a.clients;
	});
}

module.exports = TwitterTopics;
<|endoftext|>


<commit_before>import { withComponent, shadow, props } from 'skatejs';
import { hasNativeShadowDomSupport } from '../utils/environment';
import { findParentTag } from '../utils/find-parent-tag';

export function BoltBase(Base = HTMLElement) {
  return class extends Base {
    constructor(...args) {
      super(...args);
      this._wasInitiallyRendered = false;
    }

    connectedCallback() {
      // NOTE: it's SUPER important that setupSlots is run during the component's connectedCallback lifecycle event
      // Without this, browsers like IE 11 won't re-render as expected when props change!
      if (!this.slots) {
        this.setupSlots();
      }

      // Automatically force a component to render if no props exist BUT props are defined.
      if (
        Object.keys(this.props).length !== 0 &&
        Object.keys(this._props).length === 0
      ) {
        this.updated();
      }
    }

    setupSlots() {
      // Automatically adjust which inner element inside the custom element gets used as the base when evaluating slotted children. Necessary when including deeply nested slots in the initial HTML being rendered, which might include a few wrapping containers that get removed when the JavaScript kicks in. <-- this is how we get slotted buttons to work!
      const isShadowRootSelector = this.querySelector('[is="shadow-root"]');
      if (isShadowRootSelector) {
        if (isShadowRootSelector.childNodes) {
          this.slots = this._checkSlots(isShadowRootSelector.childNodes);
        } else {
          this.slots = this._checkSlots();
        }
      } else {
        this.slots = this._checkSlots();
      }
    }

    setupShadow() {
      if (
        this.useShadow === false ||
        findParentTag(this, 'FORM') ||
        this.getAttribute('no-shadow') !== null
      ) {
        this.useShadow = false;
      } else {
        this.useShadow = hasNativeShadowDomSupport;
      }
    }

    get renderRoot() {
      // ensure every component instance renders to the light DOM when needed (ex. if nested inside of a form, render to the light DOM)
      // this ensures that things work as expected, even when a component gets removed / re-added to the page
      this.setupShadow();

      // @todo: add debug flag the build to allow conditionally enabling / disabling this extra slot setup check here.
      if (!this.slots) {
        this.setupSlots(); // hotfix to ensure heavily nested elements containing text-nodes like <replace-with-children> re-render consistently in browsers that don't natively support custom elements Fixes wwwd8-2678
      }

      if (hasNativeShadowDomSupport && this.useShadow === true) {
        return super.renderRoot || shadow(this);
      } else {
        return this;
      }
    }

    addStyles(stylesheet) {
      let styles = Array.from(stylesheet);
      styles = styles.join(' ');

      if (this.useShadow && this.renderStyles) {
        return this.renderStyles(styles);
      }
    }

    // Inspired by https://codepen.io/jovdb/pen/ddRZKo
    _checkSlots(selector = this.childNodes) {
      const slots = { default: [] };

      // Loop through nodelist
      selector.forEach(function(child, index, nodelist) {
        const slotName = child.getAttribute ? child.getAttribute('slot') : null;

        if (!slotName) {
          slots.default.push(child);
        } else if (slots[slotName]) {
          slots[slotName].push(child);
        } else {
          slots[slotName] = [];
          slots[slotName].push(child);
        }
      });

      return slots;
    }

    disconnectedCallback() {
      this.disconnecting && this.disconnecting();
      this.disconnected && this.disconnected();
    }

    rendered() {
      if (!this._wasInitiallyRendered) {
        this._wasInitiallyRendered = true;

        // Fired only once, when the component has finished rendering for the first time.
        this.dispatchEvent(
          new CustomEvent('ready', {
            detail: {
              name: this.tagName.toLowerCase(),
              shadowDom: this.useShadow ? true : false,
            },
            bubbles: true,
          }),
        );
      }

      // Fired every time an element has rendered
      this.dispatchEvent(
        new CustomEvent('rendered', {
          detail: {
            name: this.tagName.toLowerCase(),
            shadowDom: this.useShadow ? true : false,
          },
          bubbles: true,
        }),
      );
    }
  };
}
<commit_msg>refactor: remove auto `updated()` call in component's connected callback — fixes issue with components using context not always having data available initially<commit_after>import { withComponent, shadow, props } from 'skatejs';
import { hasNativeShadowDomSupport } from '../utils/environment';
import { findParentTag } from '../utils/find-parent-tag';

export function BoltBase(Base = HTMLElement) {
  return class extends Base {
    constructor(...args) {
      super(...args);
      this._wasInitiallyRendered = false;
    }

    connectedCallback() {
      // NOTE: it's SUPER important that setupSlots is run during the component's connectedCallback lifecycle event
      // Without this, browsers like IE 11 won't re-render as expected when props change!
      if (!this.slots) {
        this.setupSlots();
      }
    }

    setupSlots() {
      // Automatically adjust which inner element inside the custom element gets used as the base when evaluating slotted children. Necessary when including deeply nested slots in the initial HTML being rendered, which might include a few wrapping containers that get removed when the JavaScript kicks in. <-- this is how we get slotted buttons to work!
      const isShadowRootSelector = this.querySelector('[is="shadow-root"]');
      if (isShadowRootSelector) {
        if (isShadowRootSelector.childNodes) {
          this.slots = this._checkSlots(isShadowRootSelector.childNodes);
        } else {
          this.slots = this._checkSlots();
        }
      } else {
        this.slots = this._checkSlots();
      }
    }

    setupShadow() {
      if (
        this.useShadow === false ||
        findParentTag(this, 'FORM') ||
        this.getAttribute('no-shadow') !== null
      ) {
        this.useShadow = false;
      } else {
        this.useShadow = hasNativeShadowDomSupport;
      }
    }

    get renderRoot() {
      // ensure every component instance renders to the light DOM when needed (ex. if nested inside of a form, render to the light DOM)
      // this ensures that things work as expected, even when a component gets removed / re-added to the page
      this.setupShadow();

      // @todo: add debug flag the build to allow conditionally enabling / disabling this extra slot setup check here.
      if (!this.slots) {
        this.setupSlots(); // hotfix to ensure heavily nested elements containing text-nodes like <replace-with-children> re-render consistently in browsers that don't natively support custom elements Fixes wwwd8-2678
      }

      if (hasNativeShadowDomSupport && this.useShadow === true) {
        return super.renderRoot || shadow(this);
      } else {
        return this;
      }
    }

    addStyles(stylesheet) {
      let styles = Array.from(stylesheet);
      styles = styles.join(' ');

      if (this.useShadow && this.renderStyles) {
        return this.renderStyles(styles);
      }
    }

    // Inspired by https://codepen.io/jovdb/pen/ddRZKo
    _checkSlots(selector = this.childNodes) {
      const slots = { default: [] };

      // Loop through nodelist
      selector.forEach(function(child, index, nodelist) {
        const slotName = child.getAttribute ? child.getAttribute('slot') : null;

        if (!slotName) {
          slots.default.push(child);
        } else if (slots[slotName]) {
          slots[slotName].push(child);
        } else {
          slots[slotName] = [];
          slots[slotName].push(child);
        }
      });

      return slots;
    }

    disconnectedCallback() {
      this.disconnecting && this.disconnecting();
      this.disconnected && this.disconnected();
    }

    rendered() {
      if (!this._wasInitiallyRendered) {
        this._wasInitiallyRendered = true;

        // Fired only once, when the component has finished rendering for the first time.
        this.dispatchEvent(
          new CustomEvent('ready', {
            detail: {
              name: this.tagName.toLowerCase(),
              shadowDom: this.useShadow ? true : false,
            },
            bubbles: true,
          }),
        );
      }

      // Fired every time an element has rendered
      this.dispatchEvent(
        new CustomEvent('rendered', {
          detail: {
            name: this.tagName.toLowerCase(),
            shadowDom: this.useShadow ? true : false,
          },
          bubbles: true,
        }),
      );
    }
  };
}
<|endoftext|>


<commit_before>const path = require('path');
const pkgUp = require('pkg-up');
let shelljs = require('shelljs');
import {AccountParser, dappPath, defaultHost, dockerHostSwap, embarkPath} from 'embark-utils';

class Simulator {
  constructor(options) {
    this.blockchainConfig = options.blockchainConfig;
    this.logger = options.logger;
  }

  /*eslint complexity: ["error", 26]*/
  run(options) {
    const cmds = [];

    const host = (dockerHostSwap(options.host || this.blockchainConfig.rpcHost) || defaultHost);
    const configPort = this.blockchainConfig.wsRPC ? this.blockchainConfig.rpcPort : this.blockchainConfig.wsPort;
    let port = parseInt((options.port || configPort || 8545), 10);

    cmds.push("-p " + port);
    cmds.push("-h " + host);
    cmds.push("-l " + (options.gasLimit || this.blockchainConfig.targetGasLimit || 8000000));

    // adding mnemonic only if it is defined in the blockchainConfig or options
    let mnemonicAccount = this.blockchainConfig.accounts ? this.blockchainConfig.accounts.find(acc => acc.mnemonic) : {};
    mnemonicAccount = mnemonicAccount || {};
    const simulatorMnemonic = mnemonicAccount.mnemonic || options.simulatorMnemonic;

    if (simulatorMnemonic) {
      cmds.push("--mnemonic \"" + (simulatorMnemonic) + "\"");
    }
    cmds.push("-a " + (options.numAccounts || mnemonicAccount.numAddresses || 10));
    cmds.push("-e " + (options.defaultBalance || mnemonicAccount.balance || 100));

    // as ganache-cli documentation explains, the simulatorAccounts configuration overrides a mnemonic
    let simulatorAccounts = this.blockchainConfig.simulatorAccounts || options.simulatorAccounts;
    if (simulatorAccounts && simulatorAccounts.length > 0) {
      let web3 = new (require('web3'))();
      let parsedAccounts;
      try {
        parsedAccounts = AccountParser.parseAccountsConfig(simulatorAccounts, web3, dappPath(), this.logger);
      } catch (e) {
        this.logger.error(e.message);
        process.exit(1);
      }
      parsedAccounts.forEach((account) => {
        let cmd = '--account="' + account.privateKey + ',' + account.hexBalance + '"';
        cmds.push(cmd);
      });
    }

    // adding blocktime only if it is defined in the blockchainConfig or options
    let simulatorBlocktime = this.blockchainConfig.simulatorBlocktime || options.simulatorBlocktime;
    if (simulatorBlocktime) {
      cmds.push("-b \"" + (simulatorBlocktime) + "\"");
    }

    // Setting up network id for simulator from blockchainConfig or options.
    // Otherwise ganache-cli would make random network id.
    let networkId = this.blockchainConfig.networkId || options.networkId;
    if (networkId) { // Don't handle networkId=="0" because it is not a valid networkId for ganache-cli.
      cmds.push("--networkId " + networkId);
    }

    this.runCommand(cmds, host, port);
  }

  runCommand(cmds) {
    const ganache_main = require.resolve('ganache-cli', {paths: [embarkPath('node_modules')]});
    const ganache_json = pkgUp.sync(path.dirname(ganache_main));
    const ganache_root = path.dirname(ganache_json);
    const ganache_bin = require(ganache_json).bin;
    let ganache;
    if (typeof ganache_bin === 'string') {
      ganache = path.join(ganache_root, ganache_bin);
    } else {
      ganache = path.join(ganache_root, ganache_bin['ganache-cli']);
    }

    const programName = 'ganache-cli';
    const program = ganache;
    this.logger.info(`running: ${programName} ${cmds.join(' ')}`);

    shelljs.exec(`node ${program} ${cmds.join(' ')}`, {async: true});
  }
}

module.exports = Simulator;
<commit_msg>fix(@embark/simulator): fix port used in simulator<commit_after>const path = require('path');
const pkgUp = require('pkg-up');
let shelljs = require('shelljs');
import {AccountParser, dappPath, defaultHost, dockerHostSwap, embarkPath} from 'embark-utils';

class Simulator {
  constructor(options) {
    this.blockchainConfig = options.blockchainConfig;
    this.logger = options.logger;
  }

  /*eslint complexity: ["error", 26]*/
  run(options) {
    const cmds = [];

    const host = (dockerHostSwap(options.host || this.blockchainConfig.rpcHost) || defaultHost);
    const configPort = this.blockchainConfig.wsRPC ? this.blockchainConfig.wsPort : this.blockchainConfig.rpcPort;
    let port = parseInt((options.port || configPort || 8545), 10);

    cmds.push("-p " + port);
    cmds.push("-h " + host);
    cmds.push("-l " + (options.gasLimit || this.blockchainConfig.targetGasLimit || 8000000));

    // adding mnemonic only if it is defined in the blockchainConfig or options
    let mnemonicAccount = this.blockchainConfig.accounts ? this.blockchainConfig.accounts.find(acc => acc.mnemonic) : {};
    mnemonicAccount = mnemonicAccount || {};
    const simulatorMnemonic = mnemonicAccount.mnemonic || options.simulatorMnemonic;

    if (simulatorMnemonic) {
      cmds.push("--mnemonic \"" + (simulatorMnemonic) + "\"");
    }
    cmds.push("-a " + (options.numAccounts || mnemonicAccount.numAddresses || 10));
    cmds.push("-e " + (options.defaultBalance || mnemonicAccount.balance || 100));

    // as ganache-cli documentation explains, the simulatorAccounts configuration overrides a mnemonic
    let simulatorAccounts = this.blockchainConfig.simulatorAccounts || options.simulatorAccounts;
    if (simulatorAccounts && simulatorAccounts.length > 0) {
      let web3 = new (require('web3'))();
      let parsedAccounts;
      try {
        parsedAccounts = AccountParser.parseAccountsConfig(simulatorAccounts, web3, dappPath(), this.logger);
      } catch (e) {
        this.logger.error(e.message);
        process.exit(1);
      }
      parsedAccounts.forEach((account) => {
        let cmd = '--account="' + account.privateKey + ',' + account.hexBalance + '"';
        cmds.push(cmd);
      });
    }

    // adding blocktime only if it is defined in the blockchainConfig or options
    let simulatorBlocktime = this.blockchainConfig.simulatorBlocktime || options.simulatorBlocktime;
    if (simulatorBlocktime) {
      cmds.push("-b \"" + (simulatorBlocktime) + "\"");
    }

    // Setting up network id for simulator from blockchainConfig or options.
    // Otherwise ganache-cli would make random network id.
    let networkId = this.blockchainConfig.networkId || options.networkId;
    if (networkId) { // Don't handle networkId=="0" because it is not a valid networkId for ganache-cli.
      cmds.push("--networkId " + networkId);
    }

    this.runCommand(cmds, host, port);
  }

  runCommand(cmds) {
    const ganache_main = require.resolve('ganache-cli', {paths: [embarkPath('node_modules')]});
    const ganache_json = pkgUp.sync(path.dirname(ganache_main));
    const ganache_root = path.dirname(ganache_json);
    const ganache_bin = require(ganache_json).bin;
    let ganache;
    if (typeof ganache_bin === 'string') {
      ganache = path.join(ganache_root, ganache_bin);
    } else {
      ganache = path.join(ganache_root, ganache_bin['ganache-cli']);
    }

    const programName = 'ganache-cli';
    const program = ganache;
    this.logger.info(`running: ${programName} ${cmds.join(' ')}`);

    shelljs.exec(`node ${program} ${cmds.join(' ')}`, {async: true});
  }
}

module.exports = Simulator;
<|endoftext|>


<commit_before>import Ember from 'ember-metal/core'; // deprecateFunc
import { get } from 'ember-metal/property_get';
import isNone from 'ember-metal/is_none';

/**
  Verifies that a value is `null` or an empty string, empty array,
  or empty function.

  Constrains the rules on `Ember.isNone` by returning false for empty
  string and empty arrays.

  ```javascript
  Ember.isEmpty();                // true
  Ember.isEmpty(null);            // true
  Ember.isEmpty(undefined);       // true
  Ember.isEmpty('');              // true
  Ember.isEmpty([]);              // true
  Ember.isEmpty('Adam Hawkins');  // false
  Ember.isEmpty([0,1,2]);         // false
  ```

  @method isEmpty
  @for Ember
  @param {Object} obj Value to test
  @return {Boolean}
*/
function isEmpty(obj) {
  return isNone(obj) || (obj.length === 0 && typeof obj !== 'function') ||
    (typeof obj === 'object' && get(obj, 'length') === 0);
}

var empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", isEmpty);

export default isEmpty;
export {
  isEmpty,
  empty
};
<commit_msg>[DOC beta] Fix isEmpty description<commit_after>import Ember from 'ember-metal/core'; // deprecateFunc
import { get } from 'ember-metal/property_get';
import isNone from 'ember-metal/is_none';

/**
  Verifies that a value is `null` or an empty string, empty array,
  or empty function.

  Constrains the rules on `Ember.isNone` by returning true for empty
  string and empty arrays.

  ```javascript
  Ember.isEmpty();                // true
  Ember.isEmpty(null);            // true
  Ember.isEmpty(undefined);       // true
  Ember.isEmpty('');              // true
  Ember.isEmpty([]);              // true
  Ember.isEmpty('Adam Hawkins');  // false
  Ember.isEmpty([0,1,2]);         // false
  ```

  @method isEmpty
  @for Ember
  @param {Object} obj Value to test
  @return {Boolean}
*/
function isEmpty(obj) {
  return isNone(obj) || (obj.length === 0 && typeof obj !== 'function') ||
    (typeof obj === 'object' && get(obj, 'length') === 0);
}

var empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", isEmpty);

export default isEmpty;
export {
  isEmpty,
  empty
};
<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global Backbone*/
/*global _*/
var GDP = GDP || {};

GDP.ADVANCED = GDP.ADVANCED || {};

$(document).ready(function() {
	"use strict";

	// Preload all templates and partials
	var TEMPLATES = [
		'hub',
		'spatial',
		'datadetail',
		'process'
	];

	var PARTIALS = [];

	GDP.ADVANCED.templates = GDP.util.templateLoader('js/advanced/templates/');

	var loadConfigModel = $.when($.ajax('config', {
			success: function (data) {
				GDP.config = new GDP.model.Config(data);
			}
		}));

	// I need to load up my config model since one of the views I load depends on it
	// Load up the process collection based on incoming model definitions from the config object

	var loadTemplates = GDP.ADVANCED.templates.loadTemplates(TEMPLATES);
	var loadPartials = GDP.ADVANCED.templates.registerPartials(PARTIALS);

	$.when(loadTemplates, loadPartials, loadConfigModel).always(function () {
		GDP.processes = new GDP.ADVANCED.collection.Processes(_.map(GDP.config.get('process').processes, function (m) {
			return new GDP.ADVANCED.model.Process(m);
		}));
		GDP.ADVANCED.router = new GDP.ADVANCED.controller.AdvancedRouter();
		Backbone.history.start();
	});

});
<commit_msg>Re-added log4js<commit_after>/*jslint browser: true*/
/*global Backbone*/
/*global _*/
/*global log4javascript*/
var GDP = GDP || {};

GDP.ADVANCED = GDP.ADVANCED || {};

$(document).ready(function() {
	"use strict";

	// Preload all templates and partials
	var TEMPLATES = [
		'hub',
		'spatial',
		'datadetail',
		'process'
	];

	var PARTIALS = [];

	GDP.ADVANCED.templates = GDP.util.templateLoader('js/advanced/templates/');

	var loadConfigModel = $.when($.ajax('config', {
			success: function (data) {
				GDP.config = new GDP.model.Config(data);
			}
		}));

	// I need to load up my config model since one of the views I load depends on it
	// Load up the process collection based on incoming model definitions from the config object

	var loadTemplates = GDP.ADVANCED.templates.loadTemplates(TEMPLATES);
	var loadPartials = GDP.ADVANCED.templates.registerPartials(PARTIALS);

	$.when(loadTemplates, loadPartials, loadConfigModel).always(function () {
		initializeLogging({
			LOG4JS_LOG_THRESHOLD: GDP.config ? 'debug' : 'info'
		});
		GDP.logger = log4javascript.getLogger();
		GDP.processes = new GDP.ADVANCED.collection.Processes(_.map(GDP.config.get('process').processes, function (m) {
			return new GDP.ADVANCED.model.Process(m);
		}));
		GDP.ADVANCED.router = new GDP.ADVANCED.controller.AdvancedRouter();
		Backbone.history.start();
	});

});
<|endoftext|>


<commit_before>import { h, defineComponent, computed, provide, getCurrentInstance } from 'vue'

import StepHeader from './StepHeader.js'

import useDark, { useDarkProps } from '../../composables/private/use-dark.js'
import usePanel, { usePanelProps, usePanelEmits } from '../../composables/private/use-panel.js'

import { stepperKey } from '../../utils/private/symbols.js'
import { hSlot, hMergeSlot, hDir } from '../../utils/private/render.js'

export default defineComponent({
  name: 'QStepper',

  props: {
    ...useDarkProps,
    ...usePanelProps,

    flat: Boolean,
    bordered: Boolean,
    alternativeLabels: Boolean,
    headerNav: Boolean,
    contracted: Boolean,
    headerClass: String,

    inactiveColor: String,
    inactiveIcon: String,
    doneIcon: String,
    doneColor: String,
    activeIcon: String,
    activeColor: String,
    errorIcon: String,
    errorColor: String
  },

  emits: usePanelEmits,

  setup (props, { slots }) {
    const vm = getCurrentInstance()
    const isDark = useDark(props, vm.proxy.$q)

    const {
      updatePanelsList, isValidPanelName,
      updatePanelIndex, getPanelContent,
      getPanels, panelDirectives, goToPanel
    } = usePanel()

    provide(stepperKey, computed(() => ({
      goToPanel,
      ...props
    })))

    const classes = computed(() =>
      `q-stepper q-stepper--${ props.vertical === true ? 'vertical' : 'horizontal' }`
      + (props.flat === true || isDark.value === true ? ' q-stepper--flat no-shadow' : '')
      + (props.bordered === true || (isDark.value === true && props.flat === false) ? ' q-stepper--bordered' : '')
      + (props.contracted === true ? ' q-stepper--contracted' : '')
      + (isDark.value === true ? ' q-stepper--dark q-dark' : '')
    )

    const headerClasses = computed(() =>
      'q-stepper__header row items-stretch justify-between'
      + ` q-stepper__header--${ props.alternativeLabels === true ? 'alternative' : 'standard' }-labels`
      + (props.flat === false || props.bordered === true ? ' q-stepper__header--border' : '')
      + (props.headerClass !== void 0 ? ` ${ props.headerClass }` : '')
    )

    function getContent () {
      const top = hSlot(slots.message, [])

      if (props.vertical === true) {
        isValidPanelName(props.modelValue) && updatePanelIndex()

        const content = h('div', {
          class: 'q-stepper__content'
        }, hSlot(slots.default))

        return top === void 0
          ? [ content ]
          : top.concat(content)
      }

      return [
        h('div', { class: headerClasses.value }, getPanels().map(panel => {
          const step = panel.props

          return h(StepHeader, {
            key: step.name,
            stepper: props,
            step,
            goToPanel
          })
        }))
      ].concat(
        top,
        hDir(
          'div',
          { class: 'q-stepper__content q-panel-parent' },
          getPanelContent(),
          'cont',
          props.swipeable,
          () => panelDirectives.value
        )
      )
    }

    return () => {
      updatePanelsList(slots)

      return h('div', {
        class: classes.value
      }, hMergeSlot(slots.navigation, getContent()))
    }
  }
})
<commit_msg>refactor(QStepper): small perf tweak<commit_after>import { h, defineComponent, computed, provide, getCurrentInstance } from 'vue'

import StepHeader from './StepHeader.js'

import useDark, { useDarkProps } from '../../composables/private/use-dark.js'
import usePanel, { usePanelProps, usePanelEmits } from '../../composables/private/use-panel.js'

import { stepperKey } from '../../utils/private/symbols.js'
import { hSlot, hMergeSlot, hDir } from '../../utils/private/render.js'

export default defineComponent({
  name: 'QStepper',

  props: {
    ...useDarkProps,
    ...usePanelProps,

    flat: Boolean,
    bordered: Boolean,
    alternativeLabels: Boolean,
    headerNav: Boolean,
    contracted: Boolean,
    headerClass: String,

    inactiveColor: String,
    inactiveIcon: String,
    doneIcon: String,
    doneColor: String,
    activeIcon: String,
    activeColor: String,
    errorIcon: String,
    errorColor: String
  },

  emits: usePanelEmits,

  setup (props, { slots }) {
    const vm = getCurrentInstance()
    const isDark = useDark(props, vm.proxy.$q)

    const {
      updatePanelsList, isValidPanelName,
      updatePanelIndex, getPanelContent,
      getPanels, panelDirectives, goToPanel
    } = usePanel()

    provide(stepperKey, computed(() => ({
      goToPanel,
      ...props
    })))

    const classes = computed(() =>
      `q-stepper q-stepper--${ props.vertical === true ? 'vertical' : 'horizontal' }`
      + (props.flat === true || isDark.value === true ? ' q-stepper--flat no-shadow' : '')
      + (props.bordered === true || (isDark.value === true && props.flat === false) ? ' q-stepper--bordered' : '')
      + (props.contracted === true ? ' q-stepper--contracted' : '')
      + (isDark.value === true ? ' q-stepper--dark q-dark' : '')
    )

    const headerClasses = computed(() =>
      'q-stepper__header row items-stretch justify-between'
      + ` q-stepper__header--${ props.alternativeLabels === true ? 'alternative' : 'standard' }-labels`
      + (props.flat === false || props.bordered === true ? ' q-stepper__header--border' : '')
      + (props.headerClass !== void 0 ? ` ${ props.headerClass }` : '')
    )

    function getContent () {
      const top = hSlot(slots.message, [])

      if (props.vertical === true) {
        isValidPanelName(props.modelValue) && updatePanelIndex()

        const content = h('div', {
          class: 'q-stepper__content'
        }, hSlot(slots.default))

        return top === void 0
          ? [ content ]
          : top.concat(content)
      }

      return [
        h(
          'div',
          { class: headerClasses.value },
          getPanels().map(panel => {
            const step = panel.props

            return h(StepHeader, {
              key: step.name,
              stepper: props,
              step,
              goToPanel
            })
          })
        ),

        top,

        hDir(
          'div',
          { class: 'q-stepper__content q-panel-parent' },
          getPanelContent(),
          'cont',
          props.swipeable,
          () => panelDirectives.value
        )
      ]
    }

    return () => {
      updatePanelsList(slots)

      return h('div', {
        class: classes.value
      }, hMergeSlot(slots.navigation, getContent()))
    }
  }
})
<|endoftext|>


<commit_before>/*
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var jasig = jasig || {};

(function($, fluid){

    var displayMessage = function(that, num) {

        // display the loading message while we retrieve the desired message
        showLoadingMessage(that);

        // get the message
        var message = getMessage(that, num);

        // update the individual message display with our just-retrieved message
        var html = message.content.html ? message.content.contentString : "
" + message.content.contentString + "
";
        $(".message-content").html(html);
        $(".email-message .subject").html(message.subject);
        $(".email-message .sender").html(message.sender);
        $(".email-message .sentDate").html(message.sentDateString);

        // show the message display
        showEmailMessage(that);

        return false;
    };

    // Top-level abstraction of the user's email account;
    // needs to be re-set whenever mail is fetched.
    var account = null;

    // If true, will drop the cache entry (if present)
    // for this user on the next call to the server
    var clearCache = "false";

    /**
     * Retrieve batched email from the server
     */
    var getEmail = function(that, start, size, sortKey, sortDir) {
        if (that.cache[start] && that.cache[start][size]) {
            return that.cache[start][size];
        }

        $.ajax({
            url: that.options.accountInfoUrl,
            async: false,
            data: { pageStart: start, numberOfMessages: size, forceRefresh: clearCache },
            type: 'POST',
            dataType: "json",
            success: function(data) {
                clearCache = "false";
                account = data;
            },
            error: function(request, textStatus, error) { showErrorMessage(that, request.status); }
        });
        var messages = account.accountInfo.messages;
        that.cache[start] = that.cache[start] || [];
        that.cache[start][size] = messages;

        return messages;
    };

    var getEmailFunction = function(that) {
        return function(start, size, sortKey, sortDir) {
            return getEmail(that, start, size, sortKey, sortDir);
        };
    };

    var getMessage = function(that, messageNum) {
        var message;
        $.ajax({
            url: that.options.messageUrl,
            async: false,
            data: { messageNum: messageNum },
            type: 'POST',
            dataType: "json",
            success: function(data) { message = data.message; },
            error: function(request, textStatus, error) { showErrorMessage(that, request.status); }
        });
        return message;
    };

    var showEmailList = function(that) {
        that.locate("loadingMessage").hide();
        that.locate("emailMessage").hide();
        that.locate("errorMessage").hide();
        that.locate("emailList").show();
    };

    var showLoadingMessage = function(that) {
        that.locate("emailList").hide();
        that.locate("emailMessage").hide();
        that.locate("errorMessage").hide();
        that.locate("loadingMessage").show();
    };

    var showEmailMessage = function(that) {
        that.locate("loadingMessage").hide();
        that.locate("emailList").hide();
        that.locate("errorMessage").hide();
        that.locate("emailMessage").show();
    };

    var errorHandlers = {
        401: function(that,code) {
            var msg = "Failed to authenticate to mail store";
            that.locate("errorText").html(msg);
            that.locate("errorMessage").show();
        },
        504: function(that,code) {
            var msg = "Mail store connection failed: Gateway Timeout";
            that.locate("errorText").html(msg);
            that.locate("errorMessage").show();
        },
        'default': function(that,code) {
            var msg = "Unknown mail store error: " + code;
            that.locate("errorText").html(msg);
            that.locate("errorMessage").show();
        }
    }
    var showErrorMessage = function(that, code) {
        that.locate("loadingMessage").hide();
        that.locate("emailList").hide();
        that.locate("emailMessage").hide();
        var handler = errorHandlers[code] || errorHandlers['default'];
        handler(that,code);
    };

    var getClasses = function(idx, message) {
        var classes = "";
        if (idx % 2 == 0) classes += " portlet-section-alternate";
        if (message.unread) classes += " unread";
        if (message.answered) classes += " answered";
        if (message.deleted) classes += " deleted";
        if (message.multipart) classes += " attached";
        return classes;
    };

    var removeMessages = function(messages, cache) {
        that.locate("emailRow").each(function(index, row) {
            if (row.find(options.selectors.selectMessage).attr("checked")) {
                row.remove();
            }
        });
    };

    jasig.EmailBrowser = function(container, options) {

        var that = fluid.initView("jasig.EmailBrowser", container, options);

        that.cache = [];
        showLoadingMessage(that);

        var batchOptions = {
            batchSize: that.options.batchSize,
            pagerOptions: {
                columnDefs: [
                    { key: "select", valuebinding: "*.select",
                        components: function(row, index) {
                            return {
                                markup: '<input type="checkbox" class="select-message" name="selectMessage" value="\${*.uid}"/>',
                                decorators: [
                                    { attrs: { messageNum: '\${*.messageNumber}' } },
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                    },
                    { key: "flags", valuebinding: "*.answered",
                        components: function(row, index) {
                            return {
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            };
                        }
                    },
                    { key: "attachments", valuebinding: "*.multipart",
                        components: function(row, index) {
                            return {
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            };
                        }
                    },
                    { key: "subject", valuebinding: "*.subject",
                        components: function(row, index) {
                            return {
                                markup: "\${*.subject}",
                                decorators: [
                                    { attrs: { messageNum: '\${*.messageNumber}' } },
                                    { type: "jQuery", func: "click",
                                        args: function(){ displayMessage(that, $(this).attr("messageNum")); }
                                    },
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                    },
                    { key: "sender", valuebinding: "*.senderName",
                        components: function(row, index) {
                            return {
                                value: "\${*.senderName}",
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                    },
                    { key: "sentDate", valuebinding: "*.sentDateString",
                        components: function(row, index) {
                            return {
                                value: "\${*.sentDateString}",
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                }
                ],
                bodyRenderer: {
                    type: "fluid.pager.selfRender",
                    options: {
                        selectors: { root: "table" },
                        row: "row:"
                    }
                },
                pagerBar: {
                    type: "fluid.pager.pagerBar",
                    options: {
                        pageList: {
                            type: "fluid.pager.renderedPageList",
                            options: {
                                linkBody: "a",
                                pageStrategy: fluid.pager.gappedPageStrategy(3, 1)
                            }
                        }
                    }
                },
                model: {
                    pageSize: that.options.pageSize
                },
                listeners: that.options.listeners
            },
            dataFunction: getEmailFunction(that),
            dataLengthFunction: function() { return account.accountInfo.totalMessageCount; }
        };

        that.pager = unicon.batchedpager(that.locate("emailList"), batchOptions);

        that.refresh = function() {
            showLoadingMessage(that);
            clearCache = "true";  // Server-side cache
            that.cache = [];      // Client-side cache
            that.pager.refreshView();
            that.locate("unreadMessageCount").html(account.accountInfo.unreadMessageCount + (account.accountInfo.unreadMessageCount != 1 ? " unread messages" : " unread message"));
            showEmailList(that);
        };

        that.deleteMessage = function() {
            if (that.locate("emailRow").find("input[checked='true']").size() === 0) {
                alert("No Messages Selected.");
                return;
            }
            if (confirm("Delete Selected Messages?")) {
                showLoadingMessage(that);
                var params = that.locate("emailForm").serializeArray();
                var ajaxOptions = {
                    url: options.deleteUrl,
                    type: "POST",
                    data: params,
                    dataType: "json",
                    error: function(XMLHttpRequest, textStatus, errorThrown) {
                        showErrorMessage(that, request.status);
                    },
                    success: function(data) {
                        that.refresh();
                    }
                }
                $.ajax(ajaxOptions);
            }
        };

        that.toggleSelectAll = function() {
            var chk = $(this).attr("checked");
            that.locate("selectMessage").attr("checked", chk);
        }

        that.locate("refreshLink").click(that.refresh);
        if (account.accountInfo.deleteSupported) {
            that.locate("deleteLink").click(that.deleteMessage);
        } else {
            var anchor = that.locate("deleteLink");
            anchor.find("span").html("Delete Not Available");
            anchor.find("span").addClass("fl-text-silver");
            anchor.attr("title", "The delete feature is not supported by this mail store");
        }
        that.locate("returnLink").click(function(){ showEmailList(that); });
        that.locate("inboxLink").attr("href", account.inboxUrl);

        that.locate("selectAll").live("click", that.toggleSelectAll);

        that.locate("unreadMessageCount").html(account.accountInfo.unreadMessageCount + (account.accountInfo.unreadMessageCount != 1 ? " unread messages" : " unread message"));

        showEmailList(that);

        return that;

    };

    fluid.defaults("jasig.EmailBrowser", {
        accountInfoUrl: null,
        messageUrl: null,
        deleteUrl: null,
        pageSize: 10,
        batchSize: 20,
        selectors: {
            refreshLink: ".refresh-link",
            deleteLink: ".delete-link",
            returnLink: ".return-link",
            emailForm: "form[name='email']",
            timestamp: "input[name='timestamp']",
            selectAll: ".select-all",
            selectMessage: ".select-message",
            emailList: ".email-list",
            emailRow: ".email-row",
            emailMessage: ".email-message",
            loadingMessage: ".loading-message",
            errorMessage: ".error-message",
            errorText: ".error-message #error-text",
            unreadMessageCount: ".unread-message-count",
            inboxLink: ".inbox-link"
        },
        listeners: {}
    });

})(jQuery, fluid);
<commit_msg>NOJIRA:  Add missing semicolon<commit_after>/*
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var jasig = jasig || {};

(function($, fluid){

    var displayMessage = function(that, num) {

        // display the loading message while we retrieve the desired message
        showLoadingMessage(that);

        // get the message
        var message = getMessage(that, num);

        // update the individual message display with our just-retrieved message
        var html = message.content.html ? message.content.contentString : "
" + message.content.contentString + "
";
        $(".message-content").html(html);
        $(".email-message .subject").html(message.subject);
        $(".email-message .sender").html(message.sender);
        $(".email-message .sentDate").html(message.sentDateString);

        // show the message display
        showEmailMessage(that);

        return false;
    };

    // Top-level abstraction of the user's email account;
    // needs to be re-set whenever mail is fetched.
    var account = null;

    // If true, will drop the cache entry (if present)
    // for this user on the next call to the server
    var clearCache = "false";

    /**
     * Retrieve batched email from the server
     */
    var getEmail = function(that, start, size, sortKey, sortDir) {
        if (that.cache[start] && that.cache[start][size]) {
            return that.cache[start][size];
        }

        $.ajax({
            url: that.options.accountInfoUrl,
            async: false,
            data: { pageStart: start, numberOfMessages: size, forceRefresh: clearCache },
            type: 'POST',
            dataType: "json",
            success: function(data) {
                clearCache = "false";
                account = data;
            },
            error: function(request, textStatus, error) { showErrorMessage(that, request.status); }
        });
        var messages = account.accountInfo.messages;
        that.cache[start] = that.cache[start] || [];
        that.cache[start][size] = messages;

        return messages;
    };

    var getEmailFunction = function(that) {
        return function(start, size, sortKey, sortDir) {
            return getEmail(that, start, size, sortKey, sortDir);
        };
    };

    var getMessage = function(that, messageNum) {
        var message;
        $.ajax({
            url: that.options.messageUrl,
            async: false,
            data: { messageNum: messageNum },
            type: 'POST',
            dataType: "json",
            success: function(data) { message = data.message; },
            error: function(request, textStatus, error) { showErrorMessage(that, request.status); }
        });
        return message;
    };

    var showEmailList = function(that) {
        that.locate("loadingMessage").hide();
        that.locate("emailMessage").hide();
        that.locate("errorMessage").hide();
        that.locate("emailList").show();
    };

    var showLoadingMessage = function(that) {
        that.locate("emailList").hide();
        that.locate("emailMessage").hide();
        that.locate("errorMessage").hide();
        that.locate("loadingMessage").show();
    };

    var showEmailMessage = function(that) {
        that.locate("loadingMessage").hide();
        that.locate("emailList").hide();
        that.locate("errorMessage").hide();
        that.locate("emailMessage").show();
    };

    var errorHandlers = {
        401: function(that,code) {
            var msg = "Failed to authenticate to mail store";
            that.locate("errorText").html(msg);
            that.locate("errorMessage").show();
        },
        504: function(that,code) {
            var msg = "Mail store connection failed: Gateway Timeout";
            that.locate("errorText").html(msg);
            that.locate("errorMessage").show();
        },
        'default': function(that,code) {
            var msg = "Unknown mail store error: " + code;
            that.locate("errorText").html(msg);
            that.locate("errorMessage").show();
        }
    };

    var showErrorMessage = function(that, code) {
        that.locate("loadingMessage").hide();
        that.locate("emailList").hide();
        that.locate("emailMessage").hide();
        var handler = errorHandlers[code] || errorHandlers['default'];
        handler(that,code);
    };

    var getClasses = function(idx, message) {
        var classes = "";
        if (idx % 2 == 0) classes += " portlet-section-alternate";
        if (message.unread) classes += " unread";
        if (message.answered) classes += " answered";
        if (message.deleted) classes += " deleted";
        if (message.multipart) classes += " attached";
        return classes;
    };

    var removeMessages = function(messages, cache) {
        that.locate("emailRow").each(function(index, row) {
            if (row.find(options.selectors.selectMessage).attr("checked")) {
                row.remove();
            }
        });
    };

    jasig.EmailBrowser = function(container, options) {

        var that = fluid.initView("jasig.EmailBrowser", container, options);

        that.cache = [];
        showLoadingMessage(that);

        var batchOptions = {
            batchSize: that.options.batchSize,
            pagerOptions: {
                columnDefs: [
                    { key: "select", valuebinding: "*.select",
                        components: function(row, index) {
                            return {
                                markup: '<input type="checkbox" class="select-message" name="selectMessage" value="\${*.uid}"/>',
                                decorators: [
                                    { attrs: { messageNum: '\${*.messageNumber}' } },
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                    },
                    { key: "flags", valuebinding: "*.answered",
                        components: function(row, index) {
                            return {
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            };
                        }
                    },
                    { key: "attachments", valuebinding: "*.multipart",
                        components: function(row, index) {
                            return {
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            };
                        }
                    },
                    { key: "subject", valuebinding: "*.subject",
                        components: function(row, index) {
                            return {
                                markup: "\${*.subject}",
                                decorators: [
                                    { attrs: { messageNum: '\${*.messageNumber}' } },
                                    { type: "jQuery", func: "click",
                                        args: function(){ displayMessage(that, $(this).attr("messageNum")); }
                                    },
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                    },
                    { key: "sender", valuebinding: "*.senderName",
                        components: function(row, index) {
                            return {
                                value: "\${*.senderName}",
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                    },
                    { key: "sentDate", valuebinding: "*.sentDateString",
                        components: function(row, index) {
                            return {
                                value: "\${*.sentDateString}",
                                decorators: [
                                    { type: "addClass", classes: getClasses(index, row) }
                                ]
                            }
                        }
                }
                ],
                bodyRenderer: {
                    type: "fluid.pager.selfRender",
                    options: {
                        selectors: { root: "table" },
                        row: "row:"
                    }
                },
                pagerBar: {
                    type: "fluid.pager.pagerBar",
                    options: {
                        pageList: {
                            type: "fluid.pager.renderedPageList",
                            options: {
                                linkBody: "a",
                                pageStrategy: fluid.pager.gappedPageStrategy(3, 1)
                            }
                        }
                    }
                },
                model: {
                    pageSize: that.options.pageSize
                },
                listeners: that.options.listeners
            },
            dataFunction: getEmailFunction(that),
            dataLengthFunction: function() { return account.accountInfo.totalMessageCount; }
        };

        that.pager = unicon.batchedpager(that.locate("emailList"), batchOptions);

        that.refresh = function() {
            showLoadingMessage(that);
            clearCache = "true";  // Server-side cache
            that.cache = [];      // Client-side cache
            that.pager.refreshView();
            that.locate("unreadMessageCount").html(account.accountInfo.unreadMessageCount + (account.accountInfo.unreadMessageCount != 1 ? " unread messages" : " unread message"));
            showEmailList(that);
        };

        that.deleteMessage = function() {
            if (that.locate("emailRow").find("input[checked='true']").size() === 0) {
                alert("No Messages Selected.");
                return;
            }
            if (confirm("Delete Selected Messages?")) {
                showLoadingMessage(that);
                var params = that.locate("emailForm").serializeArray();
                var ajaxOptions = {
                    url: options.deleteUrl,
                    type: "POST",
                    data: params,
                    dataType: "json",
                    error: function(XMLHttpRequest, textStatus, errorThrown) {
                        showErrorMessage(that, request.status);
                    },
                    success: function(data) {
                        that.refresh();
                    }
                }
                $.ajax(ajaxOptions);
            }
        };

        that.toggleSelectAll = function() {
            var chk = $(this).attr("checked");
            that.locate("selectMessage").attr("checked", chk);
        }

        that.locate("refreshLink").click(that.refresh);
        if (account.accountInfo.deleteSupported) {
            that.locate("deleteLink").click(that.deleteMessage);
        } else {
            var anchor = that.locate("deleteLink");
            anchor.find("span").html("Delete Not Available");
            anchor.find("span").addClass("fl-text-silver");
            anchor.attr("title", "The delete feature is not supported by this mail store");
        }
        that.locate("returnLink").click(function(){ showEmailList(that); });
        that.locate("inboxLink").attr("href", account.inboxUrl);

        that.locate("selectAll").live("click", that.toggleSelectAll);

        that.locate("unreadMessageCount").html(account.accountInfo.unreadMessageCount + (account.accountInfo.unreadMessageCount != 1 ? " unread messages" : " unread message"));

        showEmailList(that);

        return that;

    };

    fluid.defaults("jasig.EmailBrowser", {
        accountInfoUrl: null,
        messageUrl: null,
        deleteUrl: null,
        pageSize: 10,
        batchSize: 20,
        selectors: {
            refreshLink: ".refresh-link",
            deleteLink: ".delete-link",
            returnLink: ".return-link",
            emailForm: "form[name='email']",
            timestamp: "input[name='timestamp']",
            selectAll: ".select-all",
            selectMessage: ".select-message",
            emailList: ".email-list",
            emailRow: ".email-row",
            emailMessage: ".email-message",
            loadingMessage: ".loading-message",
            errorMessage: ".error-message",
            errorText: ".error-message #error-text",
            unreadMessageCount: ".unread-message-count",
            inboxLink: ".inbox-link"
        },
        listeners: {}
    });

})(jQuery, fluid);
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react';
import shallowCompare from 'react-addons-shallow-compare';
import {Link} from 'react-router';
import _ from 'lodash';

const HostsTable = React.createClass({
  propTypes: {
    hosts: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string,
      cpu: PropTypes.number,
      load: PropTypes.number,
      apps: PropTypes.arrayOf(PropTypes.string.isRequired),
    })),
    source: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
    }).isRequired,
  },

  getInitialState() {
    return {
      searchTerm: '',
      sortDirection: null,
      sortKey: null,
    };
  },

  filter(allHosts, searchTerm) {
    return allHosts.filter((h) => {
      const apps = h.apps ? h.apps.join(', ') : '';
      // search each tag for the presence of the search term
      let tagResult = false;
      if (h.tags) {
        tagResult = Object.keys(h.tags).reduce((acc, key) => {
          return acc || h.tags[key].search(searchTerm) !== -1;
        }, false);
      } else {
        tagResult = false;
      }
      return (
        h.name.search(searchTerm) !== -1 ||
        apps.search(searchTerm) !== -1 ||
        tagResult
      );
    });
  },

  sort(hosts, key, direction) {
    switch (direction) {
      case 'asc':
        return _.sortBy(hosts, (e) => e[key]);
      case 'desc':
        return _.sortBy(hosts, (e) => e[key]).reverse();
      default:
        return hosts;
    }
  },

  updateSearchTerm(term) {
    this.setState({searchTerm: term});
  },

  updateSort(key) {
    // if we're using the key, reverse order; otherwise, set it with ascending
    if (this.state.sortKey === key) {
      const reverseDirection = (this.state.sortDirection === 'asc' ? 'desc' : 'asc');
      this.setState({sortDirection: reverseDirection});
    } else {
      this.setState({sortKey: key, sortDirection: 'asc'});
    }
  },

  sortableClasses(key) {
    if (this.state.sortKey === key) {
      if (this.state.sortDirection === 'asc') {
        return "sortable-header sorting-up";
      }
      return "sortable-header sorting-down";
    }
    return "sortable-header";
  },

  render() {
    const {searchTerm, sortKey, sortDirection} = this.state;
    const {hosts, source} = this.props;
    const sortedHosts = this.sort(this.filter(hosts, searchTerm), sortKey, sortDirection);
    const hostCount = sortedHosts.length;

    let hostsTitle;
    if (hostCount === 1) {
      hostsTitle = `${hostCount} Host`;
    } else if (hostCount > 1) {
      hostsTitle = `${hostCount} Hosts`;
    } else {
      hostsTitle = `Loading Hosts...`;
    }

    return (

{hostsTitle}

          <SearchBar onSearch={this.updateSearchTerm} />

                 this.updateSort('name')} className={this.sortableClasses('name')}>Hostname
                Status
                 this.updateSort('cpu')} className={this.sortableClasses('cpu')}>CPU
                 this.updateSort('load')} className={this.sortableClasses('load')}>Load
                Apps

              {
                sortedHosts.map((h) => {
                  return <HostRow key={h.name} host={h} source={source} />;
                })
              }

    );
  },
});

const HostRow = React.createClass({
  propTypes: {
    source: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
    }).isRequired,
    host: PropTypes.shape({
      name: PropTypes.string,
      cpu: PropTypes.number,
      load: PropTypes.number,
      deltaUptime: PropTypes.number.required,
      apps: PropTypes.arrayOf(PropTypes.string.isRequired),
    }),
  },

  shouldComponentUpdate(nextProps) {
    return shallowCompare(this, nextProps);
  },

  render() {
    const {host, source} = this.props;
    const {name, cpu, load, apps = []} = host;

    let stateStr = "";
    if (host.deltaUptime < 0) {
      stateStr = "table-dot dot-critical";
    } else if (host.deltaUptime > 0) {
      stateStr = "table-dot dot-success";
    } else {
      stateStr = "table-dot dot-danger";
    }

    return (

        <Link to={`/sources/${source.id}/hosts/${name}`}>{name}</Link>

        {isNaN(cpu) ? 'N/A' : `${cpu.toFixed(2)}%`}
        {isNaN(load) ? 'N/A' : `${load.toFixed(2)}`}

          {apps.map((app, index) => {
            return (

                <Link
                  style={{marginLeft: "2px"}}
                  to={{pathname: `/sources/${source.id}/hosts/${name}`, query: {app}}}>
                  {app}
                </Link>
                {index === apps.length - 1 ? null : ', '}

            );
          })}

    );
  },
});

const SearchBar = React.createClass({
  propTypes: {
    onSearch: PropTypes.func.isRequired,
  },

  getInitialState() {
    return {
      searchTerm: '',
    };
  },

  componentWillMount() {
    const waitPeriod = 300;
    this.handleSearch = _.debounce(this.handleSearch, waitPeriod);
  },

  handleSearch() {
    this.props.onSearch(this.state.searchTerm);
  },

  handleChange() {
    this.setState({searchTerm: this.refs.searchInput.value}, this.handleSearch);
  },

  render() {
    return (

        <input
          type="text"
          className="form-control"
          placeholder="Filter by Hostname..."
          ref="searchInput"
          onChange={this.handleChange}
        />

    );
  },
});

export default HostsTable;
<commit_msg>add sort by status on hosts page<commit_after>import React, {PropTypes} from 'react';
import shallowCompare from 'react-addons-shallow-compare';
import {Link} from 'react-router';
import _ from 'lodash';

const HostsTable = React.createClass({
  propTypes: {
    hosts: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string,
      cpu: PropTypes.number,
      load: PropTypes.number,
      apps: PropTypes.arrayOf(PropTypes.string.isRequired),
    })),
    source: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
    }).isRequired,
  },

  getInitialState() {
    return {
      searchTerm: '',
      sortDirection: null,
      sortKey: null,
    };
  },

  filter(allHosts, searchTerm) {
    return allHosts.filter((h) => {
      const apps = h.apps ? h.apps.join(', ') : '';
      // search each tag for the presence of the search term
      let tagResult = false;
      if (h.tags) {
        tagResult = Object.keys(h.tags).reduce((acc, key) => {
          return acc || h.tags[key].search(searchTerm) !== -1;
        }, false);
      } else {
        tagResult = false;
      }
      return (
        h.name.search(searchTerm) !== -1 ||
        apps.search(searchTerm) !== -1 ||
        tagResult
      );
    });
  },

  sort(hosts, key, direction) {
    switch (direction) {
      case 'asc':
        return _.sortBy(hosts, (e) => e[key]);
      case 'desc':
        return _.sortBy(hosts, (e) => e[key]).reverse();
      default:
        return hosts;
    }
  },

  updateSearchTerm(term) {
    this.setState({searchTerm: term});
  },

  updateSort(key) {
    // if we're using the key, reverse order; otherwise, set it with ascending
    if (this.state.sortKey === key) {
      const reverseDirection = (this.state.sortDirection === 'asc' ? 'desc' : 'asc');
      this.setState({sortDirection: reverseDirection});
    } else {
      this.setState({sortKey: key, sortDirection: 'asc'});
    }
  },

  sortableClasses(key) {
    if (this.state.sortKey === key) {
      if (this.state.sortDirection === 'asc') {
        return "sortable-header sorting-up";
      }
      return "sortable-header sorting-down";
    }
    return "sortable-header";
  },

  render() {
    const {searchTerm, sortKey, sortDirection} = this.state;
    const {hosts, source} = this.props;
    const sortedHosts = this.sort(this.filter(hosts, searchTerm), sortKey, sortDirection);
    const hostCount = sortedHosts.length;

    let hostsTitle;
    if (hostCount === 1) {
      hostsTitle = `${hostCount} Host`;
    } else if (hostCount > 1) {
      hostsTitle = `${hostCount} Hosts`;
    } else {
      hostsTitle = `Loading Hosts...`;
    }

    return (

{hostsTitle}

          <SearchBar onSearch={this.updateSearchTerm} />

                 this.updateSort('name')} className={this.sortableClasses('name')}>Hostname
                 this.updateSort('deltaUptime')} className={this.sortableClasses('deltaUptime')}>Status
                 this.updateSort('cpu')} className={this.sortableClasses('cpu')}>CPU
                 this.updateSort('load')} className={this.sortableClasses('load')}>Load
                Apps

              {
                sortedHosts.map((h) => {
                  return <HostRow key={h.name} host={h} source={source} />;
                })
              }

    );
  },
});

const HostRow = React.createClass({
  propTypes: {
    source: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
    }).isRequired,
    host: PropTypes.shape({
      name: PropTypes.string,
      cpu: PropTypes.number,
      load: PropTypes.number,
      deltaUptime: PropTypes.number.required,
      apps: PropTypes.arrayOf(PropTypes.string.isRequired),
    }),
  },

  shouldComponentUpdate(nextProps) {
    return shallowCompare(this, nextProps);
  },

  render() {
    const {host, source} = this.props;
    const {name, cpu, load, apps = []} = host;

    let stateStr = "";
    if (host.deltaUptime < 0) {
      stateStr = "table-dot dot-critical";
    } else if (host.deltaUptime > 0) {
      stateStr = "table-dot dot-success";
    } else {
      stateStr = "table-dot dot-danger";
    }

    return (

        <Link to={`/sources/${source.id}/hosts/${name}`}>{name}</Link>

        {isNaN(cpu) ? 'N/A' : `${cpu.toFixed(2)}%`}
        {isNaN(load) ? 'N/A' : `${load.toFixed(2)}`}

          {apps.map((app, index) => {
            return (

                <Link
                  style={{marginLeft: "2px"}}
                  to={{pathname: `/sources/${source.id}/hosts/${name}`, query: {app}}}>
                  {app}
                </Link>
                {index === apps.length - 1 ? null : ', '}

            );
          })}

    );
  },
});

const SearchBar = React.createClass({
  propTypes: {
    onSearch: PropTypes.func.isRequired,
  },

  getInitialState() {
    return {
      searchTerm: '',
    };
  },

  componentWillMount() {
    const waitPeriod = 300;
    this.handleSearch = _.debounce(this.handleSearch, waitPeriod);
  },

  handleSearch() {
    this.props.onSearch(this.state.searchTerm);
  },

  handleChange() {
    this.setState({searchTerm: this.refs.searchInput.value}, this.handleSearch);
  },

  render() {
    return (

        <input
          type="text"
          className="form-control"
          placeholder="Filter by Hostname..."
          ref="searchInput"
          onChange={this.handleChange}
        />

    );
  },
});

export default HostsTable;
<|endoftext|>