<commit_before>// mob.js
//
// Movable things that can collide with other things. Entities have a position
// in world space and a velocity. Entities do not handle their own collision
// detection.
//
// Depends: utils.js

(function(global, $) {

  var defaults = {
    x: 0,
    y: 0,
    size: {
      x: 16,
      y: 16
    },
    vel: {
      x: 0,
      y: 0
    }
  };

  var Mob = function(options) {
    options = $.extend({}, defaults, options);
    this.x = options.x;
    this.y = options.y;
    this.size = {
      x: options.size.x,
      y: options.size.y
    };
    this.vel = {
      x: options.vel.x,
      y: options.vel.y
    };

    // Given a list of rects, don't let the mob move into any of them.
    this.move = function(collides) {
      collides = collides || [];
      var mob = this;
      $.each(collides, function(i, r) {
        // collide at all?
        var npx1 = mob.x + mob.vel.x;
        var npy1 = mob.y + mob.vel.y;
        var npx2 = mob.x + mob.size.x + mob.vel.x;
        var npy2 = mob.y + mob.size.y + mob.vel.y;
        if (npy2 < r.y1) {
          return;
        }
        if (npy1 > r.y2) {
          return;
        }
        if (npx2 < r.x1) {
          return;
        }
        if (npx1 > r.x2) {
          return;
        }
        // okay, we're doing this
        if (mob.vel.y < 0) {
          mob.vel.y += r.y2 - npy1;
          return;
        }
        else if (mob.vel.y > 0) {
          mob.vel.y -= npy2 - r.y1;
          return;
        }
        if (mob.vel.x < 0) {
          mob.vel.x += r.x2 - npx1;
        }
        else if (mob.vel.x > 0) {
          mob.vel.x -= npx2 - r.x1;
        }
      });
      this.x += this.vel.x;
      this.y += this.vel.y;
    };
  };

  global.Mob = Mob;

})(window, jQuery)<commit_msg>dammit, not working yet<commit_after>// mob.js
//
// Movable things that can collide with other things. Entities have a position
// in world space and a velocity. Entities do not handle their own collision
// detection.
//
// Depends: utils.js

(function(global, $) {

  var defaults = {
    x: 0,
    y: 0,
    size: {
      x: 16,
      y: 16
    },
    vel: {
      x: 0,
      y: 0
    }
  };

  var Mob = function(options) {
    options = $.extend({}, defaults, options);
    this.x = options.x;
    this.y = options.y;
    this.size = {
      x: options.size.x,
      y: options.size.y
    };
    this.vel = {
      x: options.vel.x,
      y: options.vel.y
    };

    // Given a list of rects, don't let the mob move into any of them.
    this.move = function(collides) {
      collides = collides || [];
      var mob = this;
      $.each(collides, function(i, r) {
        // collide at all?
        var npx1 = mob.x + mob.vel.x;
        var npy1 = mob.y + mob.vel.y;
        var npx2 = mob.x + mob.size.x + mob.vel.x;
        var npy2 = mob.y + mob.size.y + mob.vel.y;
        if (npy2 < r.y1) {
          return;
        }
        if (npy1 > r.y2) {
          return;
        }
        if (npx2 < r.x1) {
          return;
        }
        if (npx1 > r.x2) {
          return;
        }
        // okay, we're doing this
        if (mob.vel.y < 0) {
          mob.vel.y += r.y2 - npy1;
        }
        else if (mob.vel.y > 0) {
          mob.vel.y -= npy2 - r.y1;
        }
        if (mob.vel.x < 0) {
          mob.vel.x += r.x2 - npx1;
        }
        else if (mob.vel.x > 0) {
          mob.vel.x -= npx2 - r.x1;
        }
      });
      this.x += this.vel.x;
      this.y += this.vel.y;
    };
  };

  global.Mob = Mob;

})(window, jQuery)<|endoftext|>


<commit_before>/**
 * Schedules view. Displays periods of selected courses in a week grid.
 * @param {Object} data - Object containing schedule data as returned from the API
 * @return {undefined}
 * @memberOf Yacs.views
 */
Yacs.views.schedule = function (target) {
  target.innerHTML = HandlebarsTemplates.schedules();

  var scheduleElement = target.querySelector('#schedule-container');
  var selectionElement = target.querySelector('#selection-container')
  var leftSwitchElement = target.querySelector('#left-switch');
  var rightSwitchElement = target.querySelector('#right-switch');
  var clearButtonElement = target.querySelector('#clear-btn');
  var scheduleNumElement = target.querySelector('#schedule-num');
  var scheduleCountElement = target.querySelector('#schedule-count');
  var scheduleStatusElement = target.querySelector('#schedule-status');
  var crnListElement = target.querySelector('#crn-list');
  var schedule = new Schedule(scheduleElement);
  var scheduleData = [];
  var scheduleIndex = 0;

  /**
   * Convert military time string to minutes-since-midnight integer form.
   * This function should be deprecated in issue #102
   */
  var toMinutes = function (timeString) {
    var int = parseInt(timeString);
    return Math.floor(int / 100) * 60 + int % 100;
  }

  /**
   * Translate schedules returned by the API into a displayable form.
   * For each schedule, convert period times ro minutes-since-midnight form,
   * and collect the CRNs from each section.
   * Additionally, determine the min star time and the max end time
   * of all of the schedules.
   */
  var processSchedules = function (schedules) {
    var start = 480;
    var end = 1200;
    var processedSchedules = schedules.map(function (schedule) {
      var courseIds = [];
      var events = [];
      var crns = [];
      schedule.sections.forEach(function (section) {
        var color = courseIds.indexOf(section.course_id);
        if (color == -1) {
          courseIds.push(section.course_id);
          color = courseIds.length - 1;
        }
        crns.push(section.crn)
        section.periods.forEach(function (period) {
          start = Math.min(start, toMinutes(period.start));
          end = Math.max(end, toMinutes(period.end));
          events.push({
            start: toMinutes(period.start),
            end: toMinutes(period.end),
            day: period.day,
            colorNum: color,
            title: [
              section.department_code + ' ' + section.course_number + ' - ' + section.name,
              section.crn,
              section.instructors[0] || ''
            ],
            tooltip: section.course_name,
          });
        });
      });
      return { events: events, crns: crns };
    });
    return { schedules: processedSchedules, start: start, end: end };
  };

  /**
   * Process schedules returned by the API, and update view accordingly,
   * setting the time range of the schedule view to accomodate all schedules.
   * If no schedules are available, show the appropriate status text.
   */
  var setSchedules = function (schedules) {
    var data = processSchedules(schedules);
    scheduleData = data.schedules;
    schedule.destroy();
    schedule = new Schedule(scheduleElement,
      { timeBegin: Math.ceil((data.start) / 60) * 60,
        timeSpan: Math.ceil((data.end - data.start) / 60) * 60 });
    scheduleCountElement.textContent = scheduleData.length;
    if (scheduleData.length > 0) {
      show(0);
    } else {
      show(-1);
      if (Yacs.user.getSelections().length > 0) {
        scheduleStatusElement.textContent = "No schedules found :( Try removing some courses";
      } else {
        scheduleStatusElement.textContent = "Nothing to see here :) Try adding some courses";
      }
    }
  };

  /**
   * Query the server for schedules based on the stored selections,
   * and update the view to show the new schedules.
   * If no sections are selected, skip the call and show nil schedules.
   */
  var updateSchedules = function () {
    var selections = Yacs.user.getSelectionsRaw();
    if (selections.length > 0) {
      Yacs.models.schedules.query({ section_ids: selections,
                                    show_periods: true },
        function(data, success) {
          if (success) {
            setSchedules(data.schedules);
          } else {
            Yacs.user.clearSelections();
            setSchedules([]);
          }
      });
      clearButtonElement.disabled = false;
    } else {
      setSchedules([]);
      clearButtonElement.disabled = true;
    }
  };

  /**
   * Show schdule at given index, and display corresponding CRNs.
   * If index is -1, show nil schedule.
   */
  var show = function (index) {
    if (index == -1) {
      scheduleStatusElement.textContent = "";
      scheduleNumElement.textContent = 0;
    } else {
      schedule.setEvents(scheduleData[index].events);
      scheduleNumElement.textContent = index + 1;
      scheduleStatusStr = 'CRNs: ' + scheduleData[index].crns.join(', ');
      scheduleStatusElement.textContent = scheduleStatusStr;
    }
  };

  /**
   * Switch to schedule [[n + 1] % n] in the sequence
   */
  var next = function () {
    if (scheduleData.length > 0) {
      scheduleIndex = (++scheduleIndex < scheduleData.length ? scheduleIndex : 0);
      show(scheduleIndex);
    }
  }

  /**
   * Switch to schedule [[n - 1] % n] in the sequence
   */
  var previous = function () {
    if (scheduleData.length > 0) {
      scheduleIndex = (--scheduleIndex < 0 ? scheduleData.length - 1 : scheduleIndex);
      show(scheduleIndex);
    }
  }

  /**
   * Show next schedule if right is clicked or pressed,
   * show previous schedule if left is clicked or pressed
   */
  Yacs.on('click', leftSwitchElement, previous);
  Yacs.on('click', rightSwitchElement, next);
  Yacs.on('keydown', document, function (elem, event) { if (event.keyCode == 37) previous(); });
  Yacs.on('keydown', document, function (elem, event) { if (event.keyCode == 39) next(); });

  /**
   * Clear selections in cookie when clear button is pressed, and update
   * schedule and selctions views accordingly.
   */
  Yacs.on('click', clearButtonElement, function () {
    Yacs.user.clearSelections();
    updateSchedules();
    target.querySelectorAll('course-info').forEach(function (ci) {
      ci.classList.remove('selected');
    });
    target.querySelectorAll('section').forEach(function (s) {
      s.classList.remove('selected');
    });
  });

  /**
   * Show selected courses / sections on the schedule page.
   * Update schedules view when a course is clicked.
   * TODO: Use native event handling to update views when selection changes
   */
  var selections = Yacs.user.getSelections();
  if (selections.length > 0) {
    Yacs.models.courses.query({ section_id: selections.join(','),
                                show_sections: true,
                                show_periods: true },
      function (data, success) {
        if (success) {
          Yacs.views.courses(selectionElement, data);
          target.querySelectorAll('course').forEach(function (course) {
            Yacs.on('click', course, updateSchedules);
          });
        }
    });
  }

  updateSchedules();
};
<commit_msg>Changes for issue #139: Added missing semicolons, changed show() function to showSchedule(), next() to nextSchedule(), previous to prevSchedule(), changed target.querySelector calls to document.getElementById.<commit_after>/**
 * Schedules view. Displays periods of selected courses in a week grid.
 * @param {Object} data - Object containing schedule data as returned from the API
 * @return {undefined}
 * @memberOf Yacs.views
 */
Yacs.views.schedule = function (target) {
  target.innerHTML = HandlebarsTemplates.schedules();

  var scheduleElement = document.getElementById('#schedule-container');
  var selectionElement = document.getElementById('#selection-container');
  var leftSwitchElement = document.getElementById('#left-switch');
  var rightSwitchElement = document.getElementById('#right-switch');
  var clearButtonElement = document.getElementById('#clear-btn');
  var scheduleNumElement = document.getElementById('#schedule-num');
  var scheduleCountElement = document.getElementById('#schedule-count');
  var scheduleStatusElement = document.getElementById('#schedule-status');
  var crnListElement = document.getElementById('#crn-list');
  var schedule = new Schedule(scheduleElement);
  var scheduleData = [];
  var scheduleIndex = 0;

  /**
   * Convert military time string to minutes-since-midnight integer form.
   * This function should be deprecated in issue #102
   */
  var toMinutes = function (timeString) {
    var int = parseInt(timeString);
    return Math.floor(int / 100) * 60 + int % 100;
  };

  /**
   * Translate schedules returned by the API into a displayable form.
   * For each schedule, convert period times ro minutes-since-midnight form,
   * and collect the CRNs from each section.
   * Additionally, determine the min star time and the max end time
   * of all of the schedules.
   */
  var processSchedules = function (schedules) {
    var start = 480;
    var end = 1200;
    var processedSchedules = schedules.map(function (schedule) {
      var courseIds = [];
      var events = [];
      var crns = [];
      schedule.sections.forEach(function (section) {
        var color = courseIds.indexOf(section.course_id);
        if (color == -1) {
          courseIds.push(section.course_id);
          color = courseIds.length - 1;
        }
        crns.push(section.crn);
        section.periods.forEach(function (period) {
          start = Math.min(start, toMinutes(period.start));
          end = Math.max(end, toMinutes(period.end));
          events.push({
            start: toMinutes(period.start),
            end: toMinutes(period.end),
            day: period.day,
            colorNum: color,
            title: [
              section.department_code + ' ' + section.course_number + ' - ' + section.name,
              section.crn,
              section.instructors[0] || ''
            ],
            tooltip: section.course_name,
          });
        });
      });
      return { events: events, crns: crns };
    });
    return { schedules: processedSchedules, start: start, end: end };
  };

  /**
   * Process schedules returned by the API, and update view accordingly,
   * setting the time range of the schedule view to accomodate all schedules.
   * If no schedules are available, show the appropriate status text.
   */
  var setSchedules = function (schedules) {
    var data = processSchedules(schedules);
    scheduleData = data.schedules;
    schedule.destroy();
    schedule = new Schedule(scheduleElement,
      { timeBegin: Math.ceil((data.start) / 60) * 60,
        timeSpan: Math.ceil((data.end - data.start) / 60) * 60 });
    scheduleCountElement.textContent = scheduleData.length;
    if (scheduleData.length > 0) {
      showSchedule(0);
    } else {
      showSchedule(-1);
      if (Yacs.user.getSelections().length > 0) {
        scheduleStatusElement.textContent = "No schedules found :( Try removing some courses";
      } else {
        scheduleStatusElement.textContent = "Nothing to see here :) Try adding some courses";
      }
    }
  };

  /**
   * Query the server for schedules based on the stored selections,
   * and update the view to show the new schedules.
   * If no sections are selected, skip the call and show nil schedules.
   */
  var updateSchedules = function () {
    var selections = Yacs.user.getSelectionsRaw();
    if (selections.length > 0) {
      Yacs.models.schedules.query({ section_ids: selections,
                                    show_periods: true },
        function(data, success) {
          if (success) {
            setSchedules(data.schedules);
          } else {
            Yacs.user.clearSelections();
            setSchedules([]);
          }
      });
      clearButtonElement.disabled = false;
    } else {
      setSchedules([]);
      clearButtonElement.disabled = true;
    }
  };

  /**
   * Show schedule at given index, and display corresponding CRNs.
   * If index is -1, show nil schedule.
   */
  var showSchedule = function (index) {
    if (index == -1) {
      scheduleStatusElement.textContent = "";
      scheduleNumElement.textContent = 0;
    } else {
      schedule.setEvents(scheduleData[index].events);
      scheduleNumElement.textContent = index + 1;
      scheduleStatusStr = 'CRNs: ' + scheduleData[index].crns.join(', ');
      scheduleStatusElement.textContent = scheduleStatusStr;
    }
  };

  /**
   * Switch to schedule [[n + 1] % n] in the sequence
   */
  var nextSchedule = function () {
    if (scheduleData.length > 0) {
      scheduleIndex = (++scheduleIndex < scheduleData.length ? scheduleIndex : 0);
      showSchedule(scheduleIndex);
    }
  };

  /**
   * Switch to schedule [[n - 1] % n] in the sequence
   */
  var prevSchedule = function () {
    if (scheduleData.length > 0) {
      scheduleIndex = (--scheduleIndex < 0 ? scheduleData.length - 1 : scheduleIndex);
      showSchedule(scheduleIndex);
    }
  };

  /**
   * Show next schedule if right is clicked or pressed,
   * show previous schedule if left is clicked or pressed
   */
  Yacs.on('click', leftSwitchElement, prevSchedule);
  Yacs.on('click', rightSwitchElement, nextSchedule);
  Yacs.on('keydown', document, function (elem, event) { if (event.keyCode == 37) prevSchedule(); });
  Yacs.on('keydown', document, function (elem, event) { if (event.keyCode == 39) nextSchedule(); });

  /**
   * Clear selections in cookie when clear button is pressed, and update
   * schedule and selctions views accordingly.
   */
  Yacs.on('click', clearButtonElement, function () {
    Yacs.user.clearSelections();
    updateSchedules();
    target.querySelectorAll('course-info').forEach(function (ci) {
      ci.classList.remove('selected');
    });
    target.querySelectorAll('section').forEach(function (s) {
      s.classList.remove('selected');
    });
  });

  /**
   * Show selected courses / sections on the schedule page.
   * Update schedules view when a course is clicked.
   * TODO: Use native event handling to update views when selection changes
   */
  var selections = Yacs.user.getSelections();
  if (selections.length > 0) {
    Yacs.models.courses.query({ section_id: selections.join(','),
                                show_sections: true,
                                show_periods: true },
      function (data, success) {
        if (success) {
          Yacs.views.courses(selectionElement, data);
          target.querySelectorAll('course').forEach(function (course) {
            Yacs.on('click', course, updateSchedules);
          });
        }
    });
  }

  updateSchedules();
};
<|endoftext|>


<commit_before>'use strict';
/*global $:false */

angular.module('fbCal')
  .controller('DesktopCtrl', function ($scope, $wix, api, $log,
                                       desktopCalendar, list, fbSetup, server) {

    //things to prepare for events: order them by time and day & get time/day out
    var temp1 = {'title' : 'Concert asds duper awesome ereallt can you make it longer yve dfsdf  fsdfsd more things that are teally important baraberque nt come to omg this is the longest event ever my event to have an awesome adventure', 'time' : 'June 17th, 7:30pm', 'day' : 'Wednesday'};
    var temp2 = {'title' : 'Concert', 'time' : 'June 17th, 9pm', 'day' : 'Wednesday'};
    var temp3 = {'title' : 'Concert', 'time' : 'June 17th, 8pm', 'day' : 'Wednesday'};
    var temp4 = {'title' : 'Concertdas Concert asds duper awesome ereallt can you make it longer yve dfsdf  fsdfsd more things that are teally important baraberque nt come to omg this is the lo', 'time' : 'June 17th, 8pm', 'day' : 'Wednesday'};
    $scope.eventList = [temp1, temp2, temp3, temp4];

    $scope.listStyle = function(last) {
      return list.listStyle(last);
    };

    $scope.openModal = function(index) {
      //append event id to url
      var onClose = function(message) {
        console.log("modal closed", message);
        api.modalEvent = undefined;
      };
      console.debug('hello open modal');
      $wix.openModal("http://localhost:5000/modal/54", 900, 590, onClose);
    };

    var getSettings = function() {
      server.getUserInfo('widget').then(function(response) {
        setSettings(response);
      }, function(response) {
        console.error("Server failed to get settings");
        setSettings(response);
      });
    };

    var setSettings = function(response) {
      $scope.settings = response.settings;
      /**
       * If you want to prevent the user from using the app if they have not
       * logged in via settings, do it here.
       *
       * if (!response.active) {
       *    Active stuff here to tell user to active app.
       * }
       */
      if ($scope.settings.view === "Month") {
        desktopCalendar.setup(response.events, response.fb_event_data);
      } else {
        list.setup($scope.settings.borderWidth,
                   response.events, response.fb_event_data);
      }
    };

    /**
     * When the site owner updates the settings, this added event listener
     * allows the widget to implement these changes immediately.
     */
    $wix.addEventListener($wix.Events.SETTINGS_UPDATED, function(message) {
      console.log('message');
      console.log(message);
      if (message.settings.view === 'Month' && $scope.settings.view === 'List') {
        desktopCalendar.setup();
      } else if (message.settings.view === 'List' && $scope.settings.view === 'Month') {
        list.setup(message.borderWidth, message.borderColor);
      }
      $scope.settings = message.settings;
      $scope.$apply();
    });

    getSettings();
});<commit_msg>Updated so modal uses right link with event id attached so server knows what data to send<commit_after>'use strict';
/*global $:false */

angular.module('fbCal')
  .controller('DesktopCtrl', function ($scope, $wix, api, $log,
                                       desktopCalendar, list, fbSetup, server) {

    //things to prepare for events: order them by time and day & get time/day out
    var temp1 = {'title' : 'Concert asds duper awesome ereallt can you make it longer yve dfsdf  fsdfsd more things that are teally important baraberque nt come to omg this is the longest event ever my event to have an awesome adventure', 'time' : 'June 17th, 7:30pm', 'day' : 'Wednesday'};
    var temp2 = {'title' : 'Concert', 'time' : 'June 17th, 9pm', 'day' : 'Wednesday'};
    var temp3 = {'title' : 'Concert', 'time' : 'June 17th, 8pm', 'day' : 'Wednesday'};
    var temp4 = {'title' : 'Concertdas Concert asds duper awesome ereallt can you make it longer yve dfsdf  fsdfsd more things that are teally important baraberque nt come to omg this is the lo', 'time' : 'June 17th, 8pm', 'day' : 'Wednesday'};
    $scope.eventList = [temp1, temp2, temp3, temp4];

    $scope.listStyle = function(last) {
      return list.listStyle(last);
    };

    $scope.openModal = function(index) {
      var eventId = $scope.eventList[index].id;
      var url = 'http://localhost:5000/modal/' + eventId;
      var onClose = function(message) {
        console.log("modal closed", message);
        api.modalEvent = undefined;
      };
      console.debug('hello open modal');
      $wix.openModal(url, 900, 590, onClose);
    };

    var getSettings = function() {
      server.getUserInfo('widget').then(function(response) {
        setSettings(response);
      }, function(response) {
        console.error("Server failed to get settings");
        setSettings(response);
      });
    };

    var setSettings = function(response) {
      $scope.settings = response.settings;
      /**
       * If you want to prevent the user from using the app if they have not
       * logged in via settings, do it here.
       *
       * if (!response.active) {
       *    Active stuff here to tell user to active app.
       * }
       */
      response.fb_event_data = [{name: 'My Event (Demo for Wix App)', start_time: '2014-09-11T19:00:00-0700', location: '', timezone: 'America/Los_Angeles', id: '1512622455616642', end_time: '2014-09-11T22:00:00-0700', eventColor: '#234323'},
      {'name': 'IHS INTERACT Second Semester adsdasd asdasd asdasdas Board Applications', start_time: '2013-01-19T23:50:00-0800', location: '', timezone: 'America/Los_Angeles', id: '539472619397830', end_time: '2013-01-19T23:55:00-0800', eventColor: '#87683F'}];
      console.debug(response.fb_event_data);
      if ($scope.settings.view === "Month") {
        desktopCalendar.setup(response.fb_event_data);
      } else {
        list.setup($scope.settings.borderWidth,
                   response.fb_event_data);
      }
    };

    /**
     * When the site owner updates the settings, this added event listener
     * allows the widget to implement these changes immediately.
     */
    $wix.addEventListener($wix.Events.SETTINGS_UPDATED, function(message) {
      console.log('message');
      console.log(message);
      if (message.settings.view === 'Month' && $scope.settings.view === 'List') {
        desktopCalendar.setup();
      } else if (message.settings.view === 'List' && $scope.settings.view === 'Month') {
        $scope.eventList = list.setup(message.borderWidth, message.borderColor);
      }
      $scope.settings = message.settings;
      $scope.$apply();
    });

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


<commit_before>
const widgetize = require('widgetize');
const template = require('./TradePrices.html');
const pkg = require('./package.json');
const d3 = require('d3');

const MARGIN_TOP = 50;
const MARGIN_BOTTOM = 50;
const MARGIN_LEFT = 80;
const MARGIN_RIGHT = 20;

/**
 * Trade Prices Widget
 */
class TradePrices extends widgetize.base(HTMLElement)
{
	init()
	{
		this._width = 0;

		this._height = 0;

		this._data = [];

		this._graph = null;

		this._xAxis = null;

		this._yAxis = null;

		this._xAxisLabel = null;

		this._yAxisLabel = null;

		this._toolTip = null;

		this._xScale = null;

		this._yScale = null;

		this._toolTopLabel = null;
	}

	get width()
	{
		return this._width;
	}

	set width(value)
	{
		if (value !== this._width)
		{
			this._width = value;
			this.invalidate();
		}
	}

	get height()
	{
		return this._height;
	}

	set height(value)
	{
		if (value !== this._height)
		{
			this._height = value;
			this.invalidate();
		}
	}

	get data()
	{
		return this._data;
	}

	set data(value)
	{
		if (value !== this._data && Array.isArray(value) )
		{
			this._data = value;
			this.invalidate();
		}
	}

	attach(dom)
	{
		this._graph = d3.select(dom).append('svg')
			.attr('width', this._width)
			.attr('height', this.height);

		this._xAxis = this._graph.append('svg:g')
			.attr('class', 'x axis');

		this._xAxisLabel = this._xAxis.append('text')
			.attr('y', 40)
			.attr('class', 'axis-label')
			.text('Trade Time');

		this._yAxis = this._graph.append('svg:g')
			.attr('class', 'y axis')
			.attr('transform', 'translate(' + MARGIN_LEFT + ',0)');

		this._yAxisLabel = this._graph.append('text')
			.attr('transform', 'rotate(-90)')
			.attr('y', 0)
			.attr('dy', '1em')
			.attr('class', 'axis-label')
			.text('Trade Price');

		this._voronoiGroup = this._graph.append('svg:g')
			.attr('class', 'voronoi');
	}

	update()
	{
		let data = this._data.concat();

		data.forEach((item) => {
			item.time = new Date(item.time);
		});

		this._xScale = d3.time.scale()
			.range([MARGIN_LEFT, this._width - MARGIN_RIGHT])
			.domain([
				d3.min(data, xAxisValue),
				d3.max(data, xAxisValue)
			]);

		this._xAxis.attr('transform', 'translate(0,' + (this._height - MARGIN_BOTTOM) + ')')
             .call(xAxisFactory(this._xScale));

		this._xAxisLabel.attr('x', (this._width - MARGIN_RIGHT)/2)

		this._yScale = d3.scale.linear()
			.range([this._height - MARGIN_TOP, MARGIN_BOTTOM])
			.domain([
				d3.min(data, yAxisValue),
				d3.max(data, yAxisValue)
			]);

        this._yAxis.call(yAxisFactory(this._yScale));

		this._yAxisLabel.attr('x', 0 - (this._height / 2));

		let voronoi = d3.geom.voronoi()
			.x((d) => { return this._xScale(d.time); })
			.y((d) => { return this._yScale(d.price); })
			.clipExtent([[MARGIN_LEFT, MARGIN_TOP], [this._width - MARGIN_RIGHT, this._height - MARGIN_BOTTOM]]);

		let dataGroup = d3.nest()
			.key(item => item.exchange)
			.entries(data);

		let line = lineFactory(this._xScale, this._yScale);

		let lines = this._graph.selectAll('path.line').data(dataGroup, exchange => exchange.key);

		lines.enter().append('svg:path')
				.attr('class', exchange => {
					return 'line line-' + exchange.key;
				})
				.attr('id', exchange => {
					return 'line_' + exchange.key;
				});

		lines.transition()
			.attr('d', exchange => line(exchange.values));

		lines.exit().remove();

		let colSpace = this._width / dataGroup.length;

		let legends = this._graph.selectAll('text.legend').data(dataGroup, exchange => exchange.key);

		legends.enter().append('text')
				.attr('y', 30)
				.attr('class', exchange => {
					return 'legend legend-' + exchange.key;
				})
				.text(exchange => exchange.key);

		legends.transition()
			.attr('x', (exchange, index) => {
				return (colSpace/2) + index*colSpace;
			});

		legends.exit().remove();

		let voronoiPaths = this._voronoiGroup.selectAll('path').data(voronoi(this._data));

		voronoiPaths.enter().append('svg:path')
				.on('mouseover', () => {
					this._toolTip.style('display', null);
				})
				.on('mouseout', onMouseOut.bind(this));

		voronoiPaths.attr('d', cord => {
			return 'M' + cord.join('L') + 'Z';
		});

		voronoiPaths.exit().remove();

		this._toolTip = this._graph.append('svg:g')
			.attr('class', 'toolTip')
			.attr('width', 50)
			.attr('height', 50)
			.style('display', 'none');

		this._toolTip.append('svg:circle')
				.style('fill', 'none')
				.style('stroke', 'blue')
				.attr('x', 50)
				.attr('y', 50)
				.attr('r', 4);

		this._toolTopLabel = this._toolTip.append('svg:text')
			.attr('y', -10);
	}

}

module.exports = widgetize(pkg.name, TradePrices, template);

/* PRIVAYE */

function xAxisValue(item)
{
	return item.time;
}

function yAxisValue(item)
{
	return item.price;
}

function xAxisFactory(xScale)
{
	return d3.svg.axis()
		.scale(xScale)
		.tickFormat(d3.time.format('%H:%M'))
		.orient('bottom');
}

function yAxisFactory(yScale)
{
	return d3.svg.axis()
		.scale(yScale)
		.orient('left');
}

function lineFactory(xScale, yScale)
{
	return d3.svg.line()
		.x(item => xScale(xAxisValue(item)))
		.y(item => yScale(yAxisValue(item)));
}

function onMouseOut(cord)
{
	let trade = cord.point;

	this._toolTip.style('display', 'none');

	this._toolTip
		.attr('transform', 'translate(' + this._xScale(xAxisValue(trade)) + ',' + this._yScale(yAxisValue(trade)) + ')');

	this._toolTopLabel
		.text(trade.price);
}

<commit_msg>Sort the exchange groups<commit_after>
const widgetize = require('widgetize');
const template = require('./TradePrices.html');
const pkg = require('./package.json');
const d3 = require('d3');

const MARGIN_TOP = 50;
const MARGIN_BOTTOM = 50;
const MARGIN_LEFT = 80;
const MARGIN_RIGHT = 20;

/**
 * Trade Prices Widget
 */
class TradePrices extends widgetize.base(HTMLElement)
{
	init()
	{
		this._width = 0;

		this._height = 0;

		this._data = [];

		this._graph = null;

		this._xAxis = null;

		this._yAxis = null;

		this._xAxisLabel = null;

		this._yAxisLabel = null;

		this._toolTip = null;

		this._xScale = null;

		this._yScale = null;

		this._toolTopLabel = null;
	}

	get width()
	{
		return this._width;
	}

	set width(value)
	{
		if (value !== this._width)
		{
			this._width = value;
			this.invalidate();
		}
	}

	get height()
	{
		return this._height;
	}

	set height(value)
	{
		if (value !== this._height)
		{
			this._height = value;
			this.invalidate();
		}
	}

	get data()
	{
		return this._data;
	}

	set data(value)
	{
		if (value !== this._data && Array.isArray(value) )
		{
			this._data = value;
			this.invalidate();
		}
	}

	attach(dom)
	{
		this._graph = d3.select(dom).append('svg')
			.attr('width', this._width)
			.attr('height', this.height);

		this._xAxis = this._graph.append('svg:g')
			.attr('class', 'x axis');

		this._xAxisLabel = this._xAxis.append('text')
			.attr('y', 40)
			.attr('class', 'axis-label')
			.text('Trade Time');

		this._yAxis = this._graph.append('svg:g')
			.attr('class', 'y axis')
			.attr('transform', 'translate(' + MARGIN_LEFT + ',0)');

		this._yAxisLabel = this._graph.append('text')
			.attr('transform', 'rotate(-90)')
			.attr('y', 0)
			.attr('dy', '1em')
			.attr('class', 'axis-label')
			.text('Trade Price');

		this._voronoiGroup = this._graph.append('svg:g')
			.attr('class', 'voronoi');
	}

	update()
	{
		let data = this._data.concat();

		data.forEach((item) => {
			item.time = new Date(item.time);
		});

		this._xScale = d3.time.scale()
			.range([MARGIN_LEFT, this._width - MARGIN_RIGHT])
			.domain([
				d3.min(data, xAxisValue),
				d3.max(data, xAxisValue)
			]);

		this._xAxis.attr('transform', 'translate(0,' + (this._height - MARGIN_BOTTOM) + ')')
             .call(xAxisFactory(this._xScale));

		this._xAxisLabel.attr('x', (this._width - MARGIN_RIGHT)/2)

		this._yScale = d3.scale.linear()
			.range([this._height - MARGIN_TOP, MARGIN_BOTTOM])
			.domain([
				d3.min(data, yAxisValue),
				d3.max(data, yAxisValue)
			]);

        this._yAxis.call(yAxisFactory(this._yScale));

		this._yAxisLabel.attr('x', 0 - (this._height / 2));

		let voronoi = d3.geom.voronoi()
			.x((d) => { return this._xScale(d.time); })
			.y((d) => { return this._yScale(d.price); })
			.clipExtent([[MARGIN_LEFT, MARGIN_TOP], [this._width - MARGIN_RIGHT, this._height - MARGIN_BOTTOM]]);

		let dataGroup = d3.nest()
			.key(item => item.exchange)
			.entries(data)
			.sort(sortGroup);

		let line = lineFactory(this._xScale, this._yScale);

		let lines = this._graph.selectAll('path.line').data(dataGroup, exchange => exchange.key);

		lines.enter().append('svg:path')
				.attr('class', exchange => {
					return 'line line-' + exchange.key;
				})
				.attr('id', exchange => {
					return 'line_' + exchange.key;
				});

		lines.transition()
			.attr('d', exchange => line(exchange.values));

		lines.exit().remove();

		let colSpace = this._width / dataGroup.length;

		let legends = this._graph.selectAll('text.legend').data(dataGroup, exchange => exchange.key);

		legends.enter().append('text')
				.attr('y', 30)
				.attr('class', exchange => {
					return 'legend legend-' + exchange.key;
				})
				.text(exchange => exchange.key);

		legends.transition()
			.attr('x', (exchange, index) => {
				return (colSpace/2) + index*colSpace;
			});

		legends.exit().remove();

		let voronoiPaths = this._voronoiGroup.selectAll('path').data(voronoi(this._data));

		voronoiPaths.enter().append('svg:path')
				.on('mouseover', () => {
					this._toolTip.style('display', null);
				})
				.on('mouseout', onMouseOut.bind(this));

		voronoiPaths.attr('d', cord => {
			return 'M' + cord.join('L') + 'Z';
		});

		voronoiPaths.exit().remove();

		this._toolTip = this._graph.append('svg:g')
			.attr('class', 'toolTip')
			.attr('width', 50)
			.attr('height', 50)
			.style('display', 'none');

		this._toolTip.append('svg:circle')
				.style('fill', 'none')
				.style('stroke', 'blue')
				.attr('x', 50)
				.attr('y', 50)
				.attr('r', 4);

		this._toolTopLabel = this._toolTip.append('svg:text')
			.attr('y', -10);
	}

}

module.exports = widgetize(pkg.name, TradePrices, template);

/* PRIVAYE */

function xAxisValue(item)
{
	return item.time;
}

function yAxisValue(item)
{
	return item.price;
}

function xAxisFactory(xScale)
{
	return d3.svg.axis()
		.scale(xScale)
		.tickFormat(d3.time.format('%H:%M'))
		.orient('bottom');
}

function yAxisFactory(yScale)
{
	return d3.svg.axis()
		.scale(yScale)
		.orient('left');
}

function lineFactory(xScale, yScale)
{
	return d3.svg.line()
		.x(item => xScale(xAxisValue(item)))
		.y(item => yScale(yAxisValue(item)));
}

function onMouseOut(cord)
{
	let trade = cord.point;

	this._toolTip.style('display', 'none');

	this._toolTip
		.attr('transform', 'translate(' + this._xScale(xAxisValue(trade)) + ',' + this._yScale(yAxisValue(trade)) + ')');

	this._toolTopLabel
		.text(trade.price);
}

function sortGroup(item1, item2)
{
	if (item1.key > item2.key)
	{
		return 1;
	}
	else if (item1.key < item2.key)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}<|endoftext|>


<commit_before>import React from 'react';
import { shallow } from 'enzyme';
import { FormattedMessage } from 'react-intl';

import A from 'components/A';
import messages from '../messages';
import Footer from '../index';

describe('', () => {
  it('should render the copyright notice', () => {
    const renderedComponent = shallow(

    );
    expect(renderedComponent.contains(

        <FormattedMessage {...messages.licenseMessage} />

    )).toBe(true);
  });

  it('should render the credits', () => {
    const renderedComponent = shallow();
    expect(renderedComponent.contains(

        <FormattedMessage
          {...messages.authorMessage}
          values={{
            author: Acebusters,
          }}
        />

    )).toBe(true);
  });
});
<commit_msg>fixed footer test<commit_after>import React from 'react';
import { shallow } from 'enzyme';
import { FormattedMessage } from 'react-intl';

import A from 'components/A';
import messages from '../messages';
import Footer from '../index';

describe('', () => {
  it('should render the copyright notice', () => {
    const renderedComponent = shallow(

    );
    expect(renderedComponent.contains(

        <FormattedMessage {...messages.licenseMessage} />

    )).toBe(true);
  });

  it('should render the credits', () => {
    const renderedComponent = shallow();
    expect(renderedComponent.contains(

        <FormattedMessage
          {...messages.authorMessage}
          values={{
            author: Acebusters,
          }}
        />

    )).toBe(true);
  });
});
<|endoftext|>


<commit_before>// @flow

import * as React from 'react';
import Relay from 'react-relay/classic';
import classNames from 'classnames';
import styled from 'styled-components';

import UserAvatar from 'app/components/shared/UserAvatar';
import Dropdown from 'app/components/shared/Dropdown';
import Badge from 'app/components/shared/Badge';
import Icon from 'app/components/shared/Icon';
import SectionLoader from 'app/components/shared/SectionLoader';
import AgentsCount from 'app/components/organization/AgentsCount';
import NewChangelogsBadge from 'app/components/user/NewChangelogsBadge';
import permissions from 'app/lib/permissions';

import UserSessionStore from 'app/stores/UserSessionStore';

import NavigationButton from './navigation-button';
import DropdownButton from './dropdown-button';
import SupportDialog from './support-dialog';
import MyBuilds from './MyBuilds';

const ArrowDropdownButton = styled(DropdownButton)`
  background-repeat: no-repeat;
  background-position: center right;

  @media (min-width: 1200px) {
    background-image: url(${require('./nav-button-right-arrow.svg')});
    padding-right: 20px;
  }
`;

type Props = {
  viewer?: Object,
  organization?: {
    id: string,
    slug: string,
    name: string,
    permissions: Object
  },
  relay: Object
};

type State = {
  showingOrgDropdown: boolean,
  showingUserDropdown: boolean,
  showingSupportDialog: boolean,
  warning: boolean,
  lastDefaultTeam: ?string
};

class Navigation extends React.PureComponent<Props, State> {
  logoutFormNode: ?HTMLFormElement;
  userDropdown: ?Dropdown;

  componentDidMount() {
    this.props.relay.setVariables({ isMounted: true });
    UserSessionStore.on('change', this.handleSessionDataChange);
  }

  componentWillMount() {
    // When the page loads, we want to pull the last default team out of the UserSessionStore.
    if (this.props.organization && this.props.organization.id) {
      this.setState({
        lastDefaultTeam: UserSessionStore.get(`organization-default-team:${this.props.organization.id}`)
      });
    }
  }

  componentWillReceiveProps(nextProps) {
    // If we're moving between organizations, we need to pull out the new
    // organization's default team setting, if it's available.
    if (
      nextProps.organization && nextProps.organization.id &&
      (!this.props.organization || nextProps.organization.id !== this.props.organization.id)
    ) {
      this.setState({
        lastDefaultTeam: UserSessionStore.get(`organization-default-team:${nextProps.organization.id}`)
      });
    }
  }

  componentWillUnmount() {
    UserSessionStore.off('change', this.handleSessionDataChange);
  }

  state = {
    showingOrgDropdown: false,
    showingUserDropdown: false,
    showingSupportDialog: false,
    warning: window['_navigation'] && window['_navigation']['warning'],
    lastDefaultTeam: null
  };

  handleSessionDataChange = ({ key, newValue }) => {
    if (!this.props.organization) {
      return;
    }

    // When the UserSessionStore gets a change, if the update was to the
    // currently displayed team, update the state with the new value!
    if (key === `organization-default-team:${this.props.organization.id}`) {
      this.setState({
        lastDefaultTeam: newValue
      });
    }
  };

  handleOrgDropdownToggle = (visible) => {
    this.setState({ showingOrgDropdown: visible });
  };

  handleUserDropdownToggle = (visible) => {
    this.setState({ showingUserDropdown: visible });
  };

  handleLogoutClick = (evt) => {
    evt.preventDefault();
    if (this.logoutFormNode) {
      this.logoutFormNode.submit();
    }
  };

  handleSupportClick = () => {
    // close the support dropdown if it's open
    if (this.userDropdown && this.state.showingUserDropdown) {
      this.userDropdown.setShowing(false);
    }

    this.setState({ showingSupportDialog: true });
  };

  handleSupportDialogClose = () => {
    this.setState({ showingSupportDialog: false });
  };

  handleGraphQLExplorerClick = () => {
    // Clicking the "GraphQL Explorer" link from a `frontend` page (not an
    // old-school Rails rendered page) just changes what we render in the
    // viewport of the page. This means by default, the user dropdown doesn't
    // dissapear, but the page changes. This is a hack to hide it when you
    // click on the link.
    if (this.userDropdown) {
      this.userDropdown.setShowing(false);
    }
    this.setState({ showingUserDropdown: false });
  };

  renderTopOrganizationMenu() {
    if (this.props.organization) {
      return (

          {this.renderOrganizationMenu()}

      );
    }
  }

  renderBottomOrganizationMenu() {
    if (this.props.organization) {
      return (

            {this.renderOrganizationMenu({ paddingLeft: 0 })}

      );
    }
  }

  // Decides whether or not the organization should appear in the dropdown
  // list. The regular behavior is:
  //
  // > Don't include the org in the drop down if it's the current one
  //
  // The only exception to this rule is if the current org needs an SSO
  // authorization before the user can see any data. If the current org needs
  // SSO, then don't include it as the current one, and treat is like the
  // others.
  includeOrganizationInDropdown(org) {
    if (this.props.organization && this.props.organization.id === org.id) {
      if (!org.permissions.pipelineView.allowed && org.permissions.pipelineView.code === "sso_authorization_required") {
        return true;
      }
      return false;

    }

    return true;
  }

  renderOrganizationsList() {
    if (!this.props.viewer || !this.props.viewer.organizations) {
      return <SectionLoader />;
    }

    const nodes = [];

    this.props.viewer.organizations.edges.forEach((org) => {
      // Don't show the active organization in the selector
      if (this.includeOrganizationInDropdown(org.node)) {
        // If the org needs SSO, show a badge
        let ssoRequiredBadge;
        if (!org.node.permissions.pipelineView.allowed && org.node.permissions.pipelineView.code === "sso_authorization_required") {
          ssoRequiredBadge = (
            <Badge outline={true} className="regular">SSO</Badge>
          );
        }

        nodes.push(
          <NavigationButton
            key={org.node.slug}
            href={`/${org.node.slug}`}
            className="block"
          >
            {org.node.name}{ssoRequiredBadge}
          </NavigationButton>
        );
      }
    });

    nodes.push(
      <NavigationButton
        key="newOrganization"
        href="/organizations/new"
        className="block"
      >
        <Icon icon="plus-circle" className="icon-mr" style={{ width: 12, height: 12 }} />Create New Organization
      </NavigationButton>
    );

    if (nodes.length > 0) {
      return nodes;
    }
  }

  getOrganizationPipelinesUrl(organization) {
    let link = `/${organization.slug}`;

    // Make the link default to the user's default team, if that data exists
    if (this.state.lastDefaultTeam) {
      link = `${link}?team=${this.state.lastDefaultTeam}`;
    }

    return link;
  }

  renderOrganizationMenu(options: { paddingLeft?: number | string, className?: string } = {}) {
    const organization = this.props.organization;
    const paddingLeft = typeof options.paddingLeft === "number" ? options.paddingLeft : 15;

    if (organization) {
      return (

          {this.renderOrganizationButtons(paddingLeft)}

      );
    }
  }

  renderOrganizationButtons(paddingLeft) {
    const organization = this.props.organization;

    // This is already checked in `renderOrganizationMenu`, but we check here
    // again to make flow play nice.
    if (!organization) {
      return;
    }

    return permissions(organization.permissions).collect(
      {
        allowed: "pipelineView",
        render: () => {
          return (
            <NavigationButton key={1} className="py0" style={{ paddingLeft: paddingLeft }} href={this.getOrganizationPipelinesUrl(organization)} linkIf={true}>Pipelines</NavigationButton>
          );
        }
      },
      {
        allowed: "agentView",
        render: () => {
          return (
            <NavigationButton key={2} className="py0" href={`/organizations/${organization.slug}/agents`} linkIf={true}>
              {'Agents'}
              <Badge className="hover-lime-child"><AgentsCount organization={organization} /></Badge>
            </NavigationButton>
          );
        }
      },
      // The settings page will redirect to the first section the user has access
      // to. If they _just_ have teams view enabled, skip the redirect and go
      // straight to the teams page.
      {
        all: {
          organizationUpdate: false,
          organizationInvitationCreate: false,
          notificationServiceUpdate: false,
          organizationBillingUpdate: false,
          teamView: true
        },
        render: () => {
          return (
            <NavigationButton key={3} className="py0" href={`/organizations/${organization.slug}/teams`}>Teams</NavigationButton>
          );
        }
      },
      {
        // If any of these permissions are allowed, render the buttons
        any: [
          "organizationUpdate",
          "organizationInvitationCreate",
          "notificationServiceUpdate",
          "organizationBillingUpdate"
        ],
        render: () => {
          return [
            <NavigationButton key={4} className="py0" href={`/organizations/${organization.slug}/users`} linkIf={true}>Users</NavigationButton>,
            <NavigationButton key={5} className="py0" href={`/organizations/${organization.slug}/settings`}>Settings</NavigationButton>
          ];
        }
      }
    );
  }

  renderUserMenuLabel() {
    if (!this.props.viewer) {
      return (

          Unknown User

      );
    }

    return (
      <React.Fragment>
        <UserAvatar
          user={this.props.viewer.user}
          className="flex-none flex items-center"
          style={{ width: 26, height: 26 }}
        />

            {this.props.viewer.user.name}

      </React.Fragment>
    );
  }

  render() {
    return (

              <NavigationButton
                href="/"
                className="px3 hover-faded-children"
                style={{
                  paddingLeft: 0,
                  // sorry, I need 1 less than px3 to make the logo not flicker
                  // in Chrome 64.0.3282.140
                  paddingRight: 14
                }}
              >

              </NavigationButton>
              <NewChangelogsBadge
                className="mr2 relative"
                style={{
                  top: -5,
                  marginLeft: -8
                }}
                viewer={this.props.viewer}
                isMounted={this.props.relay.variables.isMounted}
              />

            <Dropdown
              width={250}
              className="flex"
              style={{ flex: '0 1 auto', minWidth: 0 }}
              onToggle={this.handleOrgDropdownToggle}
            >
              <ArrowDropdownButton
                className={classNames(
                  'py0 flex-auto',
                  { lime: this.state.showingOrgDropdown }
                )}
                style={{
                  flex: '0 1 auto',
                  minWidth: 0
                }}
              >

                  {this.props.organization && !this.includeOrganizationInDropdown(this.props.organization) ? this.props.organization.name : 'Organizations'}

                <Icon icon="down-triangle" className="flex-none" style={{ width: 7, height: 7, marginLeft: '.5em' }} />
              </ArrowDropdownButton>
              {this.renderOrganizationsList()}
            </Dropdown>

            {this.renderTopOrganizationMenu()}

            <MyBuilds viewer={this.props.viewer} />

            <NavigationButton
              className="py0 xs-hide sm-hide"
              href={`/docs`}
            >
              Documentation
            </NavigationButton>
            <NavigationButton
              className="py0 xs-hide sm-hide"
              onClick={this.handleSupportClick}
            >
              Support
            </NavigationButton>

            <Dropdown
              width={180}
              className="flex"
              style={{ flex: '0 1 auto', minWidth: 55 }}
              ref={(userDropdown) => this.userDropdown = userDropdown}
              onToggle={this.handleUserDropdownToggle}
            >
              <DropdownButton
                className={classNames(
                  'py0 flex-auto',
                  { lime: this.state.showingUserDropdown }
                )}
                style={{ paddingRight: 0 }}
              >
                {this.renderUserMenuLabel()}

                  <Icon
                    icon="down-triangle"
                    style={{ width: 7, height: 7, marginLeft: '.5em' }}
                  />

              </DropdownButton>

              <NavigationButton href="/user/settings">Personal Settings</NavigationButton>
              <NavigationButton href="/user/graphql/console" linkIf={true} onClick={this.handleGraphQLExplorerClick}>GraphQL Explorer Beta</NavigationButton>

                <NavigationButton className="md-hide lg-hide" href={`/docs`}>Documentation</NavigationButton>
                <NavigationButton className="md-hide lg-hide" onClick={this.handleSupportClick}>Support</NavigationButton>

              <form action="/logout" method="post" ref={(logoutFormNode) => this.logoutFormNode = logoutFormNode}>
                <input type="hidden" name="_method" value={"delete"} />
                <input type="hidden" name={window._csrf.param} value={window._csrf.token} />
                <NavigationButton href="#" onClick={this.handleLogoutClick}>
                  {this.state.warning ? 'Unassume User' : 'Logout'}
                </NavigationButton>
              </form>
            </Dropdown>

        {this.renderBottomOrganizationMenu()}

        <SupportDialog isOpen={this.state.showingSupportDialog} onRequestClose={this.handleSupportDialogClose} />

    );
  }
}

export default Relay.createContainer(Navigation, {
  initialVariables: {
    isMounted: false
  },

  fragments: {
    organization: () => Relay.QL`
        fragment on Organization {
          ${AgentsCount.getFragment('organization')}
          name
          id
          slug
          permissions {
            pipelineView {
              allowed
              code
            }
            agentView {
              allowed
            }
            organizationUpdate {
              allowed
            }
            organizationInvitationCreate {
              allowed
            }
            notificationServiceUpdate {
              allowed
            }
            organizationBillingUpdate {
              allowed
            }
            teamView {
              allowed
            }
          }
        }
      `,
    viewer: (variables) => Relay.QL`
        fragment on Viewer {
          ${MyBuilds.getFragment('viewer')}
          ${NewChangelogsBadge.getFragment('viewer', variables)}
          user {
            name
            avatar {
              url
            }
          }
          organizations(first: 100) @include(if: $isMounted) {
            edges {
              node {
                id
                name
                slug
                permissions {
                  pipelineView {
                    allowed
                    code
                  }
                }
              }
            }
          }
        }
      `
  }
});
<commit_msg>The GraphQL Explorer can come out of beta now<commit_after>// @flow

import * as React from 'react';
import Relay from 'react-relay/classic';
import classNames from 'classnames';
import styled from 'styled-components';

import UserAvatar from 'app/components/shared/UserAvatar';
import Dropdown from 'app/components/shared/Dropdown';
import Badge from 'app/components/shared/Badge';
import Icon from 'app/components/shared/Icon';
import SectionLoader from 'app/components/shared/SectionLoader';
import AgentsCount from 'app/components/organization/AgentsCount';
import NewChangelogsBadge from 'app/components/user/NewChangelogsBadge';
import permissions from 'app/lib/permissions';

import UserSessionStore from 'app/stores/UserSessionStore';

import NavigationButton from './navigation-button';
import DropdownButton from './dropdown-button';
import SupportDialog from './support-dialog';
import MyBuilds from './MyBuilds';

const ArrowDropdownButton = styled(DropdownButton)`
  background-repeat: no-repeat;
  background-position: center right;

  @media (min-width: 1200px) {
    background-image: url(${require('./nav-button-right-arrow.svg')});
    padding-right: 20px;
  }
`;

type Props = {
  viewer?: Object,
  organization?: {
    id: string,
    slug: string,
    name: string,
    permissions: Object
  },
  relay: Object
};

type State = {
  showingOrgDropdown: boolean,
  showingUserDropdown: boolean,
  showingSupportDialog: boolean,
  warning: boolean,
  lastDefaultTeam: ?string
};

class Navigation extends React.PureComponent<Props, State> {
  logoutFormNode: ?HTMLFormElement;
  userDropdown: ?Dropdown;

  componentDidMount() {
    this.props.relay.setVariables({ isMounted: true });
    UserSessionStore.on('change', this.handleSessionDataChange);
  }

  componentWillMount() {
    // When the page loads, we want to pull the last default team out of the UserSessionStore.
    if (this.props.organization && this.props.organization.id) {
      this.setState({
        lastDefaultTeam: UserSessionStore.get(`organization-default-team:${this.props.organization.id}`)
      });
    }
  }

  componentWillReceiveProps(nextProps) {
    // If we're moving between organizations, we need to pull out the new
    // organization's default team setting, if it's available.
    if (
      nextProps.organization && nextProps.organization.id &&
      (!this.props.organization || nextProps.organization.id !== this.props.organization.id)
    ) {
      this.setState({
        lastDefaultTeam: UserSessionStore.get(`organization-default-team:${nextProps.organization.id}`)
      });
    }
  }

  componentWillUnmount() {
    UserSessionStore.off('change', this.handleSessionDataChange);
  }

  state = {
    showingOrgDropdown: false,
    showingUserDropdown: false,
    showingSupportDialog: false,
    warning: window['_navigation'] && window['_navigation']['warning'],
    lastDefaultTeam: null
  };

  handleSessionDataChange = ({ key, newValue }) => {
    if (!this.props.organization) {
      return;
    }

    // When the UserSessionStore gets a change, if the update was to the
    // currently displayed team, update the state with the new value!
    if (key === `organization-default-team:${this.props.organization.id}`) {
      this.setState({
        lastDefaultTeam: newValue
      });
    }
  };

  handleOrgDropdownToggle = (visible) => {
    this.setState({ showingOrgDropdown: visible });
  };

  handleUserDropdownToggle = (visible) => {
    this.setState({ showingUserDropdown: visible });
  };

  handleLogoutClick = (evt) => {
    evt.preventDefault();
    if (this.logoutFormNode) {
      this.logoutFormNode.submit();
    }
  };

  handleSupportClick = () => {
    // close the support dropdown if it's open
    if (this.userDropdown && this.state.showingUserDropdown) {
      this.userDropdown.setShowing(false);
    }

    this.setState({ showingSupportDialog: true });
  };

  handleSupportDialogClose = () => {
    this.setState({ showingSupportDialog: false });
  };

  handleGraphQLExplorerClick = () => {
    // Clicking the "GraphQL Explorer" link from a `frontend` page (not an
    // old-school Rails rendered page) just changes what we render in the
    // viewport of the page. This means by default, the user dropdown doesn't
    // dissapear, but the page changes. This is a hack to hide it when you
    // click on the link.
    if (this.userDropdown) {
      this.userDropdown.setShowing(false);
    }
    this.setState({ showingUserDropdown: false });
  };

  renderTopOrganizationMenu() {
    if (this.props.organization) {
      return (

          {this.renderOrganizationMenu()}

      );
    }
  }

  renderBottomOrganizationMenu() {
    if (this.props.organization) {
      return (

            {this.renderOrganizationMenu({ paddingLeft: 0 })}

      );
    }
  }

  // Decides whether or not the organization should appear in the dropdown
  // list. The regular behavior is:
  //
  // > Don't include the org in the drop down if it's the current one
  //
  // The only exception to this rule is if the current org needs an SSO
  // authorization before the user can see any data. If the current org needs
  // SSO, then don't include it as the current one, and treat is like the
  // others.
  includeOrganizationInDropdown(org) {
    if (this.props.organization && this.props.organization.id === org.id) {
      if (!org.permissions.pipelineView.allowed && org.permissions.pipelineView.code === "sso_authorization_required") {
        return true;
      }
      return false;

    }

    return true;
  }

  renderOrganizationsList() {
    if (!this.props.viewer || !this.props.viewer.organizations) {
      return <SectionLoader />;
    }

    const nodes = [];

    this.props.viewer.organizations.edges.forEach((org) => {
      // Don't show the active organization in the selector
      if (this.includeOrganizationInDropdown(org.node)) {
        // If the org needs SSO, show a badge
        let ssoRequiredBadge;
        if (!org.node.permissions.pipelineView.allowed && org.node.permissions.pipelineView.code === "sso_authorization_required") {
          ssoRequiredBadge = (
            <Badge outline={true} className="regular">SSO</Badge>
          );
        }

        nodes.push(
          <NavigationButton
            key={org.node.slug}
            href={`/${org.node.slug}`}
            className="block"
          >
            {org.node.name}{ssoRequiredBadge}
          </NavigationButton>
        );
      }
    });

    nodes.push(
      <NavigationButton
        key="newOrganization"
        href="/organizations/new"
        className="block"
      >
        <Icon icon="plus-circle" className="icon-mr" style={{ width: 12, height: 12 }} />Create New Organization
      </NavigationButton>
    );

    if (nodes.length > 0) {
      return nodes;
    }
  }

  getOrganizationPipelinesUrl(organization) {
    let link = `/${organization.slug}`;

    // Make the link default to the user's default team, if that data exists
    if (this.state.lastDefaultTeam) {
      link = `${link}?team=${this.state.lastDefaultTeam}`;
    }

    return link;
  }

  renderOrganizationMenu(options: { paddingLeft?: number | string, className?: string } = {}) {
    const organization = this.props.organization;
    const paddingLeft = typeof options.paddingLeft === "number" ? options.paddingLeft : 15;

    if (organization) {
      return (

          {this.renderOrganizationButtons(paddingLeft)}

      );
    }
  }

  renderOrganizationButtons(paddingLeft) {
    const organization = this.props.organization;

    // This is already checked in `renderOrganizationMenu`, but we check here
    // again to make flow play nice.
    if (!organization) {
      return;
    }

    return permissions(organization.permissions).collect(
      {
        allowed: "pipelineView",
        render: () => {
          return (
            <NavigationButton key={1} className="py0" style={{ paddingLeft: paddingLeft }} href={this.getOrganizationPipelinesUrl(organization)} linkIf={true}>Pipelines</NavigationButton>
          );
        }
      },
      {
        allowed: "agentView",
        render: () => {
          return (
            <NavigationButton key={2} className="py0" href={`/organizations/${organization.slug}/agents`} linkIf={true}>
              {'Agents'}
              <Badge className="hover-lime-child"><AgentsCount organization={organization} /></Badge>
            </NavigationButton>
          );
        }
      },
      // The settings page will redirect to the first section the user has access
      // to. If they _just_ have teams view enabled, skip the redirect and go
      // straight to the teams page.
      {
        all: {
          organizationUpdate: false,
          organizationInvitationCreate: false,
          notificationServiceUpdate: false,
          organizationBillingUpdate: false,
          teamView: true
        },
        render: () => {
          return (
            <NavigationButton key={3} className="py0" href={`/organizations/${organization.slug}/teams`}>Teams</NavigationButton>
          );
        }
      },
      {
        // If any of these permissions are allowed, render the buttons
        any: [
          "organizationUpdate",
          "organizationInvitationCreate",
          "notificationServiceUpdate",
          "organizationBillingUpdate"
        ],
        render: () => {
          return [
            <NavigationButton key={4} className="py0" href={`/organizations/${organization.slug}/users`} linkIf={true}>Users</NavigationButton>,
            <NavigationButton key={5} className="py0" href={`/organizations/${organization.slug}/settings`}>Settings</NavigationButton>
          ];
        }
      }
    );
  }

  renderUserMenuLabel() {
    if (!this.props.viewer) {
      return (

          Unknown User

      );
    }

    return (
      <React.Fragment>
        <UserAvatar
          user={this.props.viewer.user}
          className="flex-none flex items-center"
          style={{ width: 26, height: 26 }}
        />

            {this.props.viewer.user.name}

      </React.Fragment>
    );
  }

  render() {
    return (

              <NavigationButton
                href="/"
                className="px3 hover-faded-children"
                style={{
                  paddingLeft: 0,
                  // sorry, I need 1 less than px3 to make the logo not flicker
                  // in Chrome 64.0.3282.140
                  paddingRight: 14
                }}
              >

              </NavigationButton>
              <NewChangelogsBadge
                className="mr2 relative"
                style={{
                  top: -5,
                  marginLeft: -8
                }}
                viewer={this.props.viewer}
                isMounted={this.props.relay.variables.isMounted}
              />

            <Dropdown
              width={250}
              className="flex"
              style={{ flex: '0 1 auto', minWidth: 0 }}
              onToggle={this.handleOrgDropdownToggle}
            >
              <ArrowDropdownButton
                className={classNames(
                  'py0 flex-auto',
                  { lime: this.state.showingOrgDropdown }
                )}
                style={{
                  flex: '0 1 auto',
                  minWidth: 0
                }}
              >

                  {this.props.organization && !this.includeOrganizationInDropdown(this.props.organization) ? this.props.organization.name : 'Organizations'}

                <Icon icon="down-triangle" className="flex-none" style={{ width: 7, height: 7, marginLeft: '.5em' }} />
              </ArrowDropdownButton>
              {this.renderOrganizationsList()}
            </Dropdown>

            {this.renderTopOrganizationMenu()}

            <MyBuilds viewer={this.props.viewer} />

            <NavigationButton
              className="py0 xs-hide sm-hide"
              href={`/docs`}
            >
              Documentation
            </NavigationButton>
            <NavigationButton
              className="py0 xs-hide sm-hide"
              onClick={this.handleSupportClick}
            >
              Support
            </NavigationButton>

            <Dropdown
              width={180}
              className="flex"
              style={{ flex: '0 1 auto', minWidth: 55 }}
              ref={(userDropdown) => this.userDropdown = userDropdown}
              onToggle={this.handleUserDropdownToggle}
            >
              <DropdownButton
                className={classNames(
                  'py0 flex-auto',
                  { lime: this.state.showingUserDropdown }
                )}
                style={{ paddingRight: 0 }}
              >
                {this.renderUserMenuLabel()}

                  <Icon
                    icon="down-triangle"
                    style={{ width: 7, height: 7, marginLeft: '.5em' }}
                  />

              </DropdownButton>

              <NavigationButton href="/user/settings">Personal Settings</NavigationButton>
              <NavigationButton href="/user/graphql/console" linkIf={true} onClick={this.handleGraphQLExplorerClick}>GraphQL Explorer</NavigationButton>

                <NavigationButton className="md-hide lg-hide" href={`/docs`}>Documentation</NavigationButton>
                <NavigationButton className="md-hide lg-hide" onClick={this.handleSupportClick}>Support</NavigationButton>

              <form action="/logout" method="post" ref={(logoutFormNode) => this.logoutFormNode = logoutFormNode}>
                <input type="hidden" name="_method" value={"delete"} />
                <input type="hidden" name={window._csrf.param} value={window._csrf.token} />
                <NavigationButton href="#" onClick={this.handleLogoutClick}>
                  {this.state.warning ? 'Unassume User' : 'Logout'}
                </NavigationButton>
              </form>
            </Dropdown>

        {this.renderBottomOrganizationMenu()}

        <SupportDialog isOpen={this.state.showingSupportDialog} onRequestClose={this.handleSupportDialogClose} />

    );
  }
}

export default Relay.createContainer(Navigation, {
  initialVariables: {
    isMounted: false
  },

  fragments: {
    organization: () => Relay.QL`
        fragment on Organization {
          ${AgentsCount.getFragment('organization')}
          name
          id
          slug
          permissions {
            pipelineView {
              allowed
              code
            }
            agentView {
              allowed
            }
            organizationUpdate {
              allowed
            }
            organizationInvitationCreate {
              allowed
            }
            notificationServiceUpdate {
              allowed
            }
            organizationBillingUpdate {
              allowed
            }
            teamView {
              allowed
            }
          }
        }
      `,
    viewer: (variables) => Relay.QL`
        fragment on Viewer {
          ${MyBuilds.getFragment('viewer')}
          ${NewChangelogsBadge.getFragment('viewer', variables)}
          user {
            name
            avatar {
              url
            }
          }
          organizations(first: 100) @include(if: $isMounted) {
            edges {
              node {
                id
                name
                slug
                permissions {
                  pipelineView {
                    allowed
                    code
                  }
                }
              }
            }
          }
        }
      `
  }
});
<|endoftext|>


<commit_before>app
.component('leftSidebar', {
  	templateUrl: "./components/leftSidebar/left_sidebar.html",
  	controller: function(sidebarService, dashboardService, $interval, $window, $mdSidenav, gridService) {
  		var vm = this;

        vm.searchID = "";
        vm.previousTree = [];

        init();

        vm.selectData = function(data){
            if(data.nodes.length == 0){
                sidebarService.setVehicleInfo(data.value);
            } else {
                var nodes = data.nodes;
                var count = 0;
                for(var i=0; i<nodes.length; i++){
                    if(nodes[i].nodes.length > 0){
                        count = count + 1;
                    }
                }

                //if parent of leaf node, count will be 0
                if(count==0){
                    sidebarService.setVehicleInfo(data.value);
                } else {
                    sidebarService.setVehicleInfo("");
                }
                data.active = !data.active;
            }
        }

        //function to filter data menu using search ID
        vm.filter = function(){
            //copy the data menu pulled from configuration
            vm.dataTree = angular.copy(vm.previousTree);

            vm.dataTree = vm.dataTree.filter(function f(data) {
                var name = data.name.toLowerCase();
                var searchID = vm.searchID.toLowerCase();

                if (name.includes(searchID)) return true;

                if (data.nodes) {
                    data.nodes = data.nodes.filter(f);
                    if(data.nodes.length){
                        data.active = !data.active;
                    }
                    return data.nodes.length;
                }
            });

            if(vm.dataTree.length == 0){
                $window.alert("No match found!");
                vm.dataTree = angular.copy(vm.previousTree);
            }
        }

        function init(){
            //interval to check for left sidebar, if opened, then construct the tree
            vm.interval = $interval(function(){
                var locks = dashboardService.getLock();
                var menuStatus = sidebarService.getMenuStatus();
                //check if left menu is open and data menu has not been constructed yet
                if((locks.lockLeft || $mdSidenav('left').isOpen()) && menuStatus){
                    vm.telemetry = dashboardService.getTelemetryValues();
                    if(vm.telemetry.hasOwnProperty('data')){
                        //create data tree from incoming telemetry
                        var tree = getDataTree(vm.telemetry.data);
                        if(!angular.equals(tree, vm.previousTree)){
                            vm.previousTree = angular.copy(tree);
                            vm.dataTree = angular.copy(tree);
                        }
                    } else {
                        vm.dataTree = [];
                        vm.previousTree = angular.copy(vm.dataTree);
                        //$window.alert("No telemetry data for the current mission. Please close the sidebar!");
                    }
                    sidebarService.setMenuStatus(false); //set to false when above has been executed
                }
            }, 1000);
        }

        //recursive function to create the tree structure data
        function getDataTree(data, cKey){
            var tree = [];
            for(var key in data) {
                if(data.hasOwnProperty(key)) {
                    var nodes = [];
                    var flag = true;
                    var newKey = (cKey ? cKey + "." + key : key);

                    var node = {
                        value: "",
                        key: ""
                    }

                    if(typeof data[key] === 'object'){
                        for(var key2 in data[key]) {
                            if(data[key].hasOwnProperty(key2)) {
                                //if not an object, then maybe the last nodes(metadata)
                                //like value, units etc. and need not be there in the
                                //data menu
                                if(typeof data[key][key2] !== 'object'){
                                    flag=false;
                                    break;
                                }
                            }
                        }

                        if(flag){
                            nodes = getDataTree(data[key], newKey);
                        }
                    }

                    if(nodes.length != 0) {
                        key = initCaps(key);
                    }

                    var node = {
                        'name' : key,
                        'nodes' : nodes,
                        'value' : newKey,
                        'active' : false
                    };

                    tree.push(node);
                }
            }

            //sort the tree based on the name property of the objects inside it
            tree.sort(function(a, b){
                var nameA = a.name;
                var nameB = b.name;
                if (nameA < nameB) //sort string ascending
                    return -1;
                if (nameA > nameB)
                    return 1;
                return 0;
            })

            return tree;
        }

        //function to capitalise the first letter of a string
        function initCaps(str){
            words = str.split(' ');

            for(var i = 0; i < words.length; i++) {
                var letters = words[i].split('');
                letters[0] = letters[0].toUpperCase();
                words[i] = letters.join('');
            }
            return words.join(' ');
        }

        vm.$onDestroy = function(event) {
            $interval.cancel(vm.interval );
        }
	}
});
<commit_msg>Undo changes to leftSidebar<commit_after>app
.component('leftSidebar', {
  	templateUrl: "./components/leftSidebar/left_sidebar.html",
  	controller: function(sidebarService, dashboardService, $interval, $window, $mdSidenav, gridService) {
  		var vm = this;

        vm.searchID = "";
        vm.previousTree = [];

        init();

        vm.selectData = function(data){
            if(data.nodes.length == 0){
                sidebarService.setVehicleInfo(data.value, gridService.getDashboard());
            } else {
                var nodes = data.nodes;
                var count = 0;
                for(var i=0; i<nodes.length; i++){
                    if(nodes[i].nodes.length > 0){
                        count = count + 1;
                    }
                }

                //if parent of leaf node, count will be 0
                if(count==0){
                    sidebarService.setVehicleInfo(data.value, gridService.getDashboard());
                } else {
                    sidebarService.setVehicleInfo("", gridService.getDashboard());
                }
                data.active = !data.active;
            }
        }

        //function to filter data menu using search ID
        vm.filter = function(){
            //copy the data menu pulled from configuration
            vm.dataTree = angular.copy(vm.previousTree);

            vm.dataTree = vm.dataTree.filter(function f(data) {
                var name = data.name.toLowerCase();
                var searchID = vm.searchID.toLowerCase();

                if (name.includes(searchID)) return true;

                if (data.nodes) {
                    data.nodes = data.nodes.filter(f);
                    if(data.nodes.length){
                        data.active = !data.active;
                    }
                    return data.nodes.length;
                }
            });

            if(vm.dataTree.length == 0){
                $window.alert("No match found!");
                vm.dataTree = angular.copy(vm.previousTree);
            }
        }

<<<<<<< HEAD
        function init(){
            //interval to check for left sidebar, if opened, then construct the tree
            vm.interval = $interval(function(){
                var locks = dashboardService.getLock();
                var menuStatus = sidebarService.getMenuStatus();
                //check if left menu is open and data menu has not been constructed yet
                if((locks.lockLeft || $mdSidenav('left').isOpen()) && menuStatus){
                    vm.telemetry = dashboardService.getTelemetryValues();
                    if(vm.telemetry.hasOwnProperty('data')){
                        //create data tree from incoming telemetry
                        var tree = getDataTree(vm.telemetry.data);
                        if(!angular.equals(tree, vm.previousTree)){
                            vm.previousTree = angular.copy(tree);
                            vm.dataTree = angular.copy(tree);
                        }
                    } else {
                        vm.dataTree = [];
                        vm.previousTree = angular.copy(vm.dataTree);
                        //$window.alert("No telemetry data for the current mission. Please close the sidebar!");
                    }
                    sidebarService.setMenuStatus(false); //set to false when above has been executed
                }
            }, 1000);
        }

        //recursive function to create the tree structure data
        function getDataTree(data, cKey){
            var tree = [];
            for(var key in data) {
                if(data.hasOwnProperty(key)) {
                    var nodes = [];
                    var newKey = (cKey ? cKey + "." + key : key);

                    if(typeof data[key] === 'object'){
                        nodes = getDataTree(data[key], newKey);
                    }

                    if(nodes.length != 0) {
                        key = initCaps(key);
                    }

                    var node = {
                        'name' : key,
                        'nodes' : nodes,
                        'value' : newKey,
                        'active' : false
                    };

                    tree.push(node);
                }
            }

            //sort the tree based on the name property of the objects inside it
            tree.sort(function(a, b){
                var nameA = a.name;
                var nameB = b.name;
                if (nameA < nameB) //sort string ascending
                    return -1;
                if (nameA > nameB)
                    return 1;
                return 0;
            })

            return tree;
        }

        //function to capitalise the first letter of a string
        function initCaps(str){
            words = str.split(' ');

            for(var i = 0; i < words.length; i++) {
                var letters = words[i].split('');
                letters[0] = letters[0].toUpperCase();
                words[i] = letters.join('');
            }
            return words.join(' ');
        }
    }
});
<|endoftext|>


<commit_before>define(['app', 'text!./menu.html','providers/locale'], function(app, templateHtml) { 'use strict';

    //============================================================
    //
    //============================================================
    app.directive('menu',["locale","$window",  function(locale,$window) {
        return {
            restrict: 'E',
            template : templateHtml,
            scope: {
                links: '=links',
                pull: '@?',
                search: '@?',
            },
            link: function ($scope) {
              $scope.locale=locale;
            },
            controller: function ($scope, $location) {
                // ============================================================
                //
                // ============================================================
                $scope.goToLink = function (link) {
                    if(link.children.length===0) {
                        $window.location.href=link.source;
                    }
                };
                // ============================================================
                //
                // ============================================================
                $scope.textSearch = function (keywords) {

                      if(!keywords)return;
                      $location.path('/platform/search');
                      $location.replace();
                      $location.search('keywords',[keywords]);

                };
                // ============================================================
                //
                // ============================================================
                $scope.goTo = function (link,event) {

                  if(event)
                    event.preventDefault();

                    $location.path(link);

                };
            }
        };
    }]);

});
<commit_msg>slash widget just for BBI<commit_after>define(['app', 'text!./menu.html','lodash','providers/locale'], function(app, templateHtml,_) { 'use strict';

    //============================================================
    //
    //============================================================
    app.directive('menu',["locale","$window",  function(locale,$window) {
        return {
            restrict: 'E',
            template : templateHtml,
            scope: {
                links: '=links',
                pull: '@?',
                search: '@?',
                user:'='
            },
            link: function ($scope) {
              $scope.locale=locale;

                  require(["_slaask"], function(_slaask) {

                      if(!_slaask.initialized) {
                          _slaask.init('d611635fe9b46e439afb79833e255443');
                          _slaask.initialized = true;

                      }
                  });

            },
            controller: function ($scope, $location) {
                // ============================================================
                //
                // ============================================================
                $scope.goToLink = function (link) {
                    if(link.children.length===0) {
                        $window.location.href=link.source;
                    }
                };
                // ============================================================
                //
                // ============================================================
                $scope.textSearch = function (keywords) {

                      if(!keywords)return;
                      $location.path('/platform/search');
                      $location.replace();
                      $location.search('keywords',[keywords]);

                };
                // ============================================================
                //
                // ============================================================
                $scope.goTo = function (link,event) {

                  if(event)
                    event.preventDefault();

                    $location.path(link);

                };
            }
        };
    }]);

});
<|endoftext|>


<commit_before>import constant from "./constant";
import descending from "./descending";
import identity from "./identity";
import {tau} from "./math";

export default function() {
  var value = identity,
      sortValues = descending,
      sort = null,
      startAngle = constant(0),
      endAngle = constant(tau),
      padAngle = constant(0);

  function pie(data) {
    var i,
        n = data.length,
        j,
        k,
        sum = 0,
        index = new Array(n),
        arcs = new Array(n),
        a0 = +startAngle.apply(this, arguments),
        da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)),
        a1,
        p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
        pa = p * (da < 0 ? -1 : 1),
        v;

    for (i = 0; i < n; ++i) {
      if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
        sum += v;
      }
    }

    // Optionally sort the arcs by previously-computed values or by data.
    if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
    else if (sort !== null) index.sort(function(i, j) { return sort(data[i], data[j]); });

    // Compute the arcs! They are stored in the original data's order.
    for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
      j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
        data: data[j],
        index: i,
        value: v,
        startAngle: a0,
        endAngle: a1,
        padAngle: p
      };
    }

    return arcs;
  }

  pie.value = function(_) {
    return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value;
  };

  pie.sortValues = function(_) {
    return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
  };

  pie.sort = function(_) {
    return arguments.length ? (sort = _, sortValues = null, pie) : sort;
  };

  pie.startAngle = function(_) {
    return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle;
  };

  pie.endAngle = function(_) {
    return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle;
  };

  pie.padAngle = function(_) {
    return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle;
  };

  return pie;
}
<commit_msg>Fix strict equals.<commit_after>import constant from "./constant";
import descending from "./descending";
import identity from "./identity";
import {tau} from "./math";

export default function() {
  var value = identity,
      sortValues = descending,
      sort = null,
      startAngle = constant(0),
      endAngle = constant(tau),
      padAngle = constant(0);

  function pie(data) {
    var i,
        n = data.length,
        j,
        k,
        sum = 0,
        index = new Array(n),
        arcs = new Array(n),
        a0 = +startAngle.apply(this, arguments),
        da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)),
        a1,
        p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
        pa = p * (da < 0 ? -1 : 1),
        v;

    for (i = 0; i < n; ++i) {
      if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
        sum += v;
      }
    }

    // Optionally sort the arcs by previously-computed values or by data.
    if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
    else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });

    // Compute the arcs! They are stored in the original data's order.
    for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
      j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
        data: data[j],
        index: i,
        value: v,
        startAngle: a0,
        endAngle: a1,
        padAngle: p
      };
    }

    return arcs;
  }

  pie.value = function(_) {
    return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value;
  };

  pie.sortValues = function(_) {
    return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
  };

  pie.sort = function(_) {
    return arguments.length ? (sort = _, sortValues = null, pie) : sort;
  };

  pie.startAngle = function(_) {
    return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle;
  };

  pie.endAngle = function(_) {
    return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle;
  };

  pie.padAngle = function(_) {
    return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle;
  };

  return pie;
}
<|endoftext|>


<commit_before>/**
 * Module dependancies
 */

var socketio = require('socket.io');

var io = null;

/**
 * Configure io to listen on an http server
 * @param server {HTTP} HTTP server instance
 */

function attachToServer(server){
    io = socketio(server);
}

/**
 * Give socket io access to express middleware
 * See http://stackoverflow.com/questions/25532692/how-to-share-sessions-with-socket-io-1-x-and-express-4-x/25618636#25618636
 * @param sessionMiddleware {Function} express middleware function
 */

function attachSessions(sessionMiddleware){
    io.use(function (socket, next){
        sessionMiddleware(socket.request, socket.request.res, next);
    });
}

/**
 * Start instant update system
 */

function start (){
    // Start handling on connection events
    io.on('connection', function(socket){
        console.log(socket.request.session);
    });
}

/**
 * Exports
 */

exports = module.exports = {
    attachToServer:             attachToServer
  , attachSessions:             attachSessions
  , start:                      start
};<commit_msg>Added a bunch of notification stuffs<commit_after>/**
 * Module dependancies
 */

var socketio = require('socket.io');

var io               = null
  , connectedClients = []; // Array of objects { applicantId:String, socket: SocketObj}

/**
 * Configure io to listen on an http server
 * @param server {HTTP} HTTP server instance
 */

function attachToServer(server){
    io = socketio(server);
}

/**
 * Give socket io access to express middleware
 * See http://stackoverflow.com/questions/25532692/how-to-share-sessions-with-socket-io-1-x-and-express-4-x/25618636#25618636
 * @param sessionMiddleware {Function} express middleware function
 */

function attachSessions(sessionMiddleware){
    io.use(function (socket, next){
        sessionMiddleware(socket.request, socket.request.res, next);
    });
}

/**
 * Returns index of applicant in connectedClients list. Returns
 * -1 if not found
 * @param applicantId {ObjectId} applicants id
 */

function findClient(applicantId){
    for (var i = 0; i < connectedClients.length; ++i){
        if (connectedClients[i].applicantId == String(applicantId)){
            return i;
        }
    }
    return -1;
}

/**
 * Add a applicant id and their associated socket id to connectedClients
 * list
 * @param applicantId {ObjectId} applicant id
 * @param socket {SocketObj} Socket object
 */

function addClient(applicantId, socket){
    // If applicant is already connected, nothing to do
    if (findClient(applicantId) !== -1){
        return;
    }

    connectedClients.push({applicantId : String(applicantId), socket : socket});
}

/**
 * Remove a client from the connectedClients list given their applicant id
 * @param applicantId {ObjectId} applicant id
 */

function removeClient(applicantId){
    var clientPos = findClient(applicantId);
    // If applicant isn't connected, nothing to do
    if (clientPos === -1){
        return;
    }

    connectedClients.splice(clientPos, 1);
}

/**
 * Send array of notifications to client
 * @param applicantId {ObjectId} applicant id
 * @param notifications {Array} array of notifications
 */

function sendNotifications(applicantId, notifications){
    var clientPos = findClient(applicantId);
    // If applicant isn't connected, nothing to do
    if(clientPos === -1){
        return;
    }

    connectedClients[clientPos].socket.emit('mulipleNotifications', {'notifications' : notifications});
}

/**
 * Send a single notification to client
 * @param applicantId {ObjectId} applicant id
 * @param notification {Object} notification object
 */

function sendNotification(applicantId, notification){
    var clientPos = findClient(applicantId);
    // If applicant isn't connected, nothing to do
    if(clientPos === -1){
        return;
    }

    connectedClients[clientPos].socket.emit('singleNotification', {'notification' : notification});
}

/**
 * Start instant update system
 */

function start (){
    // Start handling on connection events
    io.on('connection', function(socket){
        // In case user is authenticated already,
        // but lost socket connection temporarily
        if(socket.request.session.applicantId){
            addClient(socket.request.session.applicantId, socket);
        }

        // Login authentication
        socket.on('login', function(){
            var applicantId = socket.request.session.applicantId;
            if (applicantId) {
                addClient(applicantId, socket);
            }
        });

        socket.on('logout', function(){
            var applicantId = socket.request.session.applicantId;
            if (applicantId){
                removeClient(applicantId);
            }
        });

        socket.on('disconnect', function(){
            var applicantId = socket.request.session.applicantId;
            if (applicantId){
                removeClient(applicantId);
            }
        });
    });
}

/**
 * Exports
 */

exports = module.exports = {
    attachToServer:             attachToServer
  , attachSessions:             attachSessions
  , start:                      start
  , sendNotification:           sendNotification
  , sendNotifications:          sendNotifications
};<|endoftext|>


<commit_before>/* global angular */
import {web3, Chess} from '../../contract/Chess.sol';
angular.module('dappChess').controller('JoinGameCtrl',
  function ($rootScope, $scope, games, accounts) {
    $scope.availableAccounts = accounts.availableAccounts;

    $scope.selectedAccount = accounts.defaultAccount;
    $scope.username = null;
    $scope.gameId = null;
    $scope.games = games.list;
    $scope.openGames = games.openGames;
    $scope.etherbet = 0;

    $scope.isSelectedAccount = function (account) {
      return $scope.selectedAccount === account;
    };
    $scope.selectAccount = function (account) {
      $scope.selectedAccount = account;
    };
    $scope.setSelectedGame = function($event, game) {
      $scope.gameId = game.gameId;
      $scope.etherbet = game.value;

      $event.preventDefault();
    };
    $scope.isSelectedGame = function(game) {
      return $scope.gameId === game.gameId;
    };

    function joinGame() {
      $rootScope.$broadcast('message', 'Trying to join the game, please wait a moment...',
                            'loading', 'joingame');
      try {
        console.log('Trying to join game', $scope.gameId, $scope.username,
          {
            from: $scope.selectedAccount,
            value: web3.toWei($scope.etherbet.replace(',', '.'), 'ether')
          });
        Chess.joinGame($scope.gameId, $scope.username,
          {
            from: $scope.selectedAccount,
            value: web3.toWei($scope.etherbet.replace(',', '.'), 'ether')
          });
      }
      catch(e) {
        $rootScope.$broadcast('message', 'Could not join the game', 'loading', 'joingame');
      }
    }

    $scope.getBalance = accounts.getBalance;

    $scope.joinGame = function (form) {
      if(form.$valid) {
        joinGame();
      }
    };

  });
<commit_msg>Add logging for errors on joining the game<commit_after>/* global angular */
import {web3, Chess} from '../../contract/Chess.sol';
angular.module('dappChess').controller('JoinGameCtrl',
  function ($rootScope, $scope, games, accounts) {
    $scope.availableAccounts = accounts.availableAccounts;

    $scope.selectedAccount = accounts.defaultAccount;
    $scope.username = null;
    $scope.gameId = null;
    $scope.games = games.list;
    $scope.openGames = games.openGames;
    $scope.etherbet = 0;

    $scope.isSelectedAccount = function (account) {
      return $scope.selectedAccount === account;
    };
    $scope.selectAccount = function (account) {
      $scope.selectedAccount = account;
    };
    $scope.setSelectedGame = function($event, game) {
      $scope.gameId = game.gameId;
      $scope.etherbet = game.value;

      $event.preventDefault();
    };
    $scope.isSelectedGame = function(game) {
      return $scope.gameId === game.gameId;
    };

    function joinGame() {
      $rootScope.$broadcast('message', 'Trying to join the game, please wait a moment...',
                            'loading', 'joingame');
      try {
        console.log('Trying to join game', $scope.gameId, $scope.username,
          {
            from: $scope.selectedAccount,
            value: web3.toWei($scope.etherbet.replace(',', '.'), 'ether')
          });
        Chess.joinGame($scope.gameId, $scope.username,
          {
            from: $scope.selectedAccount,
            value: web3.toWei($scope.etherbet.replace(',', '.'), 'ether')
          });
      }
      catch(e) {
        console.log('Error joining the game', e);
        $rootScope.$broadcast('message', 'Could not join the game', 'loading', 'joingame');
      }
    }

    $scope.getBalance = accounts.getBalance;

    $scope.joinGame = function (form) {
      if(form.$valid) {
        joinGame();
      }
    };

  });
<|endoftext|>