<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Include test fixture.
GEN_INCLUDE(['net_internals_test.js']);

// Anonymous namespace
(function() {

/**
 * The task fetches a page as a way of determining if network statistics
 * (such as the aggregate received content length) change accordingly.
 * The URL is received from the previous task.
 *
 * Checks that we see all relevant events and update the corresponding table.
 *
 * @param {int} expectedLength The length of the content being loaded.
 * @param {int} faviconLength The length a favicon that is received.
 * @extends {NetInternalsTest.Task}
 * @constructor
 */
function BandwidthTask(expectedLength, faviconLength) {
  NetInternalsTest.Task.call(this);
  this.url_ = null;
  this.expectedLength_ = expectedLength;
  this.faviconLength_ = faviconLength;
  this.sessionVerified = false;
  this.historicVerified = false;
}

/**
 * The task loads data reduction proxy info.
 *
 * Checks that we see all relevant events and update the corresponding elements.
 *
 * @param {boolean} isEnabled The desired state of the data reduction proxy.
 * @extends {NetInternalsTest.Task}
 * @constructor
 */
function DataReductionProxyTask(isEnabled) {
  NetInternalsTest.Task.call(this);
  this.enabled_ = isEnabled;
  this.dataReductionProxyInfoVerified_ = false;
  this.proxySettingsReceived_ = false;
  this.badProxyChangesReceived_ = false;
}

BandwidthTask.prototype = {
  __proto__: NetInternalsTest.Task.prototype,

  /**
   * Switches to the bandwidth tab, loads a page in the background, and waits
   * for the arrival of network statistics.
   *
   * @param {string} url URL to be fetched.
   */
  start: function(url) {
    assertEquals('string', typeof url);
    this.url_ = url;
    g_browser.addSessionNetworkStatsObserver(this, true);
    g_browser.addHistoricNetworkStatsObserver(this, false);
    NetInternalsTest.switchToView('bandwidth');
    chrome.send('loadPage', [this.url_]);
  },

  /**
   * Returns the float value the specified cell of the bandwidth table.
   */
  getBandwidthTableCell_: function(row, col) {
    return parseFloat(NetInternalsTest.getTbodyText(
        BandwidthView.STATS_BOX_ID, row, col));
  },

  /**
   * Confirms that the bandwidth usage table displays the expected values.
   * Does not check exact displayed values, to avoid races, but makes sure
   * values are high enough after an event of interest.
   *
   * @param {number} col The column of the table to validate, either 1 or 2.
   * @param {number} expectedReceived Expected received content length.
   * @param {number} expectedOriginal Expected original content length.
   */
  validateBandwidthTableColumn_: function(
      col, expectedReceived, expectedOriginal) {
    var row1 = this.getBandwidthTableCell_(0, col);
    var row2 = this.getBandwidthTableCell_(1, col);
    var row3 = this.getBandwidthTableCell_(2, col);
    var row4 = this.getBandwidthTableCell_(3, col);

    var expectedReceivedKB = (expectedReceived / 1024).toFixed(1);
    var expectedOriginalKB = (expectedOriginal / 1024).toFixed(1);

    expectLE(expectedOriginalKB, row1);
    expectLE(expectedReceivedKB, row2);
    expectFalse(isNaN(row3));
    expectFalse(isNaN(row4));
  },

  /**
   * A task is complete only when session and historic counters have been
   * verified to reflect the expected number of bytes received.
   */
  completeIfDone: function() {
    if (this.historicVerified && this.sessionVerified) {
      // Check number of rows in the table.
      NetInternalsTest.checkTbodyRows(BandwidthView.STATS_BOX_ID, 4);
      this.onTaskDone();
    }
  },

  /**
   * SessionNetworkStatsObserver function.  Sanity checks the received data
   * and constructed table.

   * @param {object} networkStats State of the network session.
   */
  onSessionNetworkStatsChanged: function(networkStats) {
    if (this.isDone() || this.sessionVerified)
      return;
    // Wait until the received content length is at least the size of
    // our test page and favicon.
    var expectedLength = this.expectedLength_ + this.faviconLength_;
    if (networkStats.session_received_content_length >= expectedLength) {
      expectLE(expectedLength, networkStats.session_original_content_length);
      // Column 1 contains session information.
      this.validateBandwidthTableColumn_(1, expectedLength, expectedLength);
      this.sessionVerified = true;
      this.completeIfDone();
    }
  },

  /**
   * HistoricNetworkStatsObserver function.  Sanity checks the received data
   * and constructed table.

   * @param {object} networkStats State of the network session.
   */
  onHistoricNetworkStatsChanged: function(networkStats) {
    if (this.isDone() || this.historicVerified)
      return;
    // The received content length should be zero since the historic
    // information only updates every hour.
    var expectedLength = 0;
    // Wait until the table has changed, otherwise the columns will be NaN
    if (!isNaN(this.getBandwidthTableCell_(0, 2))) {
      expectLE(expectedLength, networkStats.historic_original_content_length);
      // Column 2 contains historic information.
      this.validateBandwidthTableColumn_(2, expectedLength, expectedLength);
      this.historicVerified = true;
      this.completeIfDone();
    }
  }
};

DataReductionProxyTask.prototype = {
  __proto__: NetInternalsTest.Task.prototype,

  /**
   * Switches to the bandwidth tab and waits for arrival of data reduction
   * proxy information.
   */
  start: function() {
    chrome.send('enableDataReductionProxy', [this.enabled_]);
    g_browser.addDataReductionProxyInfoObserver(this, true);
    g_browser.addProxySettingsObserver(this, true);
    g_browser.addBadProxiesObserver(this, true);
    NetInternalsTest.switchToView('bandwidth');
  },

  /**
   * A task is complete only when session and historic counters have been
   * verified to reflect the expected number of bytes received.
   */
  completeIfDone: function() {
    if (this.dataReductionProxyInfoVerified_) {
      this.onTaskDone();
    }
  },

  /**
   * ProxySettingsObserver function.
   *
   * @param {object} proxySettings Proxy settings.
   */
  onProxySettingsChanged: function(proxySettings) {
    if (this.isDone() || this.proxySettingsReceived_)
      return;

    this.proxySettingsReceived_ = true;
  },

  /**
   * BadProxiesObserver function.
   *
   * @param {object} badProxies Bad proxies.
   */
  onBadProxiesChanged: function(badProxies) {
    if (this.isDone() || this.badProxyChangesReceived_)
      return;

    this.badProxyChangesReceived_ = true;
  },

  /**
   * DataReductionProxyInfoObserver function.  Sanity checks the received data
   * and constructed table.

   * @param {object} info State of the data reduction proxy.
   */
  onDataReductionProxyInfoChanged: function(info) {
    if (this.isDone() ||
        this.dataReductionProxyInfoVerified_ ||
        !this.proxySettingsReceived_) {
      return;
    }

    if (info) {
      expectEquals(this.enabled_, info.enabled);
      if (this.enabled_) {
        expectEquals("Enabled", $(BandwidthView.ENABLED_ID).innerText);
        expectNotEquals('', $(BandwidthView.PRIMARY_PROXY_ID).innerText);
        expectNotEquals('', $(BandwidthView.SECONDARY_PROXY_ID).innerText);
      } else {
        expectEquals("Disabled", $(BandwidthView.ENABLED_ID).innerText);
        expectEquals('', $(BandwidthView.PRIMARY_PROXY_ID).innerText);
        expectEquals('', $(BandwidthView.SECONDARY_PROXY_ID).innerText);
        // Each event results in 2 rows, and we get 2 events since the startup
        // event starts as disabled, and we subsequently manually set it to the
        // disabled state.
        expectEquals(
            4, NetInternalsTest.getTbodyNumRows(BandwidthView.EVENTS_TBODY_ID));
      }

      this.dataReductionProxyInfoVerified_ = true;
      this.completeIfDone();
    }
  }
};

/**
 * Loads a page and checks bandwidth statistics.
 */
TEST_F('NetInternalsTest', 'netInternalsSessionBandwidthSucceed', function() {
  var taskQueue = new NetInternalsTest.TaskQueue(true);
  taskQueue.addTask(
      new NetInternalsTest.GetTestServerURLTask('files/title1.html'));
  // Load a page with a content length of 66 bytes and a 45-byte favicon.
  taskQueue.addTask(new BandwidthTask(66, 45));
  taskQueue.run();
});

/**
 * Checks data reduction proxy info when it is enabled.
 */
TEST_F('NetInternalsTest', 'netInternalsDataReductionProxyEnabled', function() {
  var taskQueue = new NetInternalsTest.TaskQueue(true);
  taskQueue.addTask(new DataReductionProxyTask(true));
  taskQueue.run();
});

/**
 * Checks data reduction proxy info when it is disabled.
 */
TEST_F('NetInternalsTest',
    'netInternalsDataReductionProxyDisabled', function() {
  var taskQueue = new NetInternalsTest.TaskQueue(true);
  taskQueue.addTask(new DataReductionProxyTask(false));
  taskQueue.run();
});

})();  // Anonymous namespace
<commit_msg>Disable NetInternalsTest.netInternalsDataReductionProxyEnabled which is flaky on Linux<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Include test fixture.
GEN_INCLUDE(['net_internals_test.js']);

// Anonymous namespace
(function() {

/**
 * The task fetches a page as a way of determining if network statistics
 * (such as the aggregate received content length) change accordingly.
 * The URL is received from the previous task.
 *
 * Checks that we see all relevant events and update the corresponding table.
 *
 * @param {int} expectedLength The length of the content being loaded.
 * @param {int} faviconLength The length a favicon that is received.
 * @extends {NetInternalsTest.Task}
 * @constructor
 */
function BandwidthTask(expectedLength, faviconLength) {
  NetInternalsTest.Task.call(this);
  this.url_ = null;
  this.expectedLength_ = expectedLength;
  this.faviconLength_ = faviconLength;
  this.sessionVerified = false;
  this.historicVerified = false;
}

/**
 * The task loads data reduction proxy info.
 *
 * Checks that we see all relevant events and update the corresponding elements.
 *
 * @param {boolean} isEnabled The desired state of the data reduction proxy.
 * @extends {NetInternalsTest.Task}
 * @constructor
 */
function DataReductionProxyTask(isEnabled) {
  NetInternalsTest.Task.call(this);
  this.enabled_ = isEnabled;
  this.dataReductionProxyInfoVerified_ = false;
  this.proxySettingsReceived_ = false;
  this.badProxyChangesReceived_ = false;
}

BandwidthTask.prototype = {
  __proto__: NetInternalsTest.Task.prototype,

  /**
   * Switches to the bandwidth tab, loads a page in the background, and waits
   * for the arrival of network statistics.
   *
   * @param {string} url URL to be fetched.
   */
  start: function(url) {
    assertEquals('string', typeof url);
    this.url_ = url;
    g_browser.addSessionNetworkStatsObserver(this, true);
    g_browser.addHistoricNetworkStatsObserver(this, false);
    NetInternalsTest.switchToView('bandwidth');
    chrome.send('loadPage', [this.url_]);
  },

  /**
   * Returns the float value the specified cell of the bandwidth table.
   */
  getBandwidthTableCell_: function(row, col) {
    return parseFloat(NetInternalsTest.getTbodyText(
        BandwidthView.STATS_BOX_ID, row, col));
  },

  /**
   * Confirms that the bandwidth usage table displays the expected values.
   * Does not check exact displayed values, to avoid races, but makes sure
   * values are high enough after an event of interest.
   *
   * @param {number} col The column of the table to validate, either 1 or 2.
   * @param {number} expectedReceived Expected received content length.
   * @param {number} expectedOriginal Expected original content length.
   */
  validateBandwidthTableColumn_: function(
      col, expectedReceived, expectedOriginal) {
    var row1 = this.getBandwidthTableCell_(0, col);
    var row2 = this.getBandwidthTableCell_(1, col);
    var row3 = this.getBandwidthTableCell_(2, col);
    var row4 = this.getBandwidthTableCell_(3, col);

    var expectedReceivedKB = (expectedReceived / 1024).toFixed(1);
    var expectedOriginalKB = (expectedOriginal / 1024).toFixed(1);

    expectLE(expectedOriginalKB, row1);
    expectLE(expectedReceivedKB, row2);
    expectFalse(isNaN(row3));
    expectFalse(isNaN(row4));
  },

  /**
   * A task is complete only when session and historic counters have been
   * verified to reflect the expected number of bytes received.
   */
  completeIfDone: function() {
    if (this.historicVerified && this.sessionVerified) {
      // Check number of rows in the table.
      NetInternalsTest.checkTbodyRows(BandwidthView.STATS_BOX_ID, 4);
      this.onTaskDone();
    }
  },

  /**
   * SessionNetworkStatsObserver function.  Sanity checks the received data
   * and constructed table.

   * @param {object} networkStats State of the network session.
   */
  onSessionNetworkStatsChanged: function(networkStats) {
    if (this.isDone() || this.sessionVerified)
      return;
    // Wait until the received content length is at least the size of
    // our test page and favicon.
    var expectedLength = this.expectedLength_ + this.faviconLength_;
    if (networkStats.session_received_content_length >= expectedLength) {
      expectLE(expectedLength, networkStats.session_original_content_length);
      // Column 1 contains session information.
      this.validateBandwidthTableColumn_(1, expectedLength, expectedLength);
      this.sessionVerified = true;
      this.completeIfDone();
    }
  },

  /**
   * HistoricNetworkStatsObserver function.  Sanity checks the received data
   * and constructed table.

   * @param {object} networkStats State of the network session.
   */
  onHistoricNetworkStatsChanged: function(networkStats) {
    if (this.isDone() || this.historicVerified)
      return;
    // The received content length should be zero since the historic
    // information only updates every hour.
    var expectedLength = 0;
    // Wait until the table has changed, otherwise the columns will be NaN
    if (!isNaN(this.getBandwidthTableCell_(0, 2))) {
      expectLE(expectedLength, networkStats.historic_original_content_length);
      // Column 2 contains historic information.
      this.validateBandwidthTableColumn_(2, expectedLength, expectedLength);
      this.historicVerified = true;
      this.completeIfDone();
    }
  }
};

DataReductionProxyTask.prototype = {
  __proto__: NetInternalsTest.Task.prototype,

  /**
   * Switches to the bandwidth tab and waits for arrival of data reduction
   * proxy information.
   */
  start: function() {
    chrome.send('enableDataReductionProxy', [this.enabled_]);
    g_browser.addDataReductionProxyInfoObserver(this, true);
    g_browser.addProxySettingsObserver(this, true);
    g_browser.addBadProxiesObserver(this, true);
    NetInternalsTest.switchToView('bandwidth');
  },

  /**
   * A task is complete only when session and historic counters have been
   * verified to reflect the expected number of bytes received.
   */
  completeIfDone: function() {
    if (this.dataReductionProxyInfoVerified_) {
      this.onTaskDone();
    }
  },

  /**
   * ProxySettingsObserver function.
   *
   * @param {object} proxySettings Proxy settings.
   */
  onProxySettingsChanged: function(proxySettings) {
    if (this.isDone() || this.proxySettingsReceived_)
      return;

    this.proxySettingsReceived_ = true;
  },

  /**
   * BadProxiesObserver function.
   *
   * @param {object} badProxies Bad proxies.
   */
  onBadProxiesChanged: function(badProxies) {
    if (this.isDone() || this.badProxyChangesReceived_)
      return;

    this.badProxyChangesReceived_ = true;
  },

  /**
   * DataReductionProxyInfoObserver function.  Sanity checks the received data
   * and constructed table.

   * @param {object} info State of the data reduction proxy.
   */
  onDataReductionProxyInfoChanged: function(info) {
    if (this.isDone() ||
        this.dataReductionProxyInfoVerified_ ||
        !this.proxySettingsReceived_) {
      return;
    }

    if (info) {
      expectEquals(this.enabled_, info.enabled);
      if (this.enabled_) {
        expectEquals("Enabled", $(BandwidthView.ENABLED_ID).innerText);
        expectNotEquals('', $(BandwidthView.PRIMARY_PROXY_ID).innerText);
        expectNotEquals('', $(BandwidthView.SECONDARY_PROXY_ID).innerText);
      } else {
        expectEquals("Disabled", $(BandwidthView.ENABLED_ID).innerText);
        expectEquals('', $(BandwidthView.PRIMARY_PROXY_ID).innerText);
        expectEquals('', $(BandwidthView.SECONDARY_PROXY_ID).innerText);
        // Each event results in 2 rows, and we get 2 events since the startup
        // event starts as disabled, and we subsequently manually set it to the
        // disabled state.
        expectEquals(
            4, NetInternalsTest.getTbodyNumRows(BandwidthView.EVENTS_TBODY_ID));
      }

      this.dataReductionProxyInfoVerified_ = true;
      this.completeIfDone();
    }
  }
};

/**
 * Loads a page and checks bandwidth statistics.
 */
TEST_F('NetInternalsTest', 'netInternalsSessionBandwidthSucceed', function() {
  var taskQueue = new NetInternalsTest.TaskQueue(true);
  taskQueue.addTask(
      new NetInternalsTest.GetTestServerURLTask('files/title1.html'));
  // Load a page with a content length of 66 bytes and a 45-byte favicon.
  taskQueue.addTask(new BandwidthTask(66, 45));
  taskQueue.run();
});

/**
 * Checks data reduction proxy info when it is enabled.
 */
TEST_F('NetInternalsTest',
       'DISABLED_netInternalsDataReductionProxyEnabled',
       function() {
  var taskQueue = new NetInternalsTest.TaskQueue(true);
  taskQueue.addTask(new DataReductionProxyTask(true));
  taskQueue.run();
});

/**
 * Checks data reduction proxy info when it is disabled.
 */
TEST_F('NetInternalsTest',
    'netInternalsDataReductionProxyDisabled', function() {
  var taskQueue = new NetInternalsTest.TaskQueue(true);
  taskQueue.addTask(new DataReductionProxyTask(false));
  taskQueue.run();
});

})();  // Anonymous namespace
<|endoftext|>


<commit_before>import angular from 'angular'
import ace from 'angular-ui-ace'

export default class EditContentController {
  constructor ($scope, $http, Auth, User, topics, topic, topicPromiseEC, $location, Flash) {
    $scope.topic = topic.data
    $scope.topicsEC = topicPromiseEC

    $scope.editor = {}
    $scope.editors = []

    $scope.newQuestion = {}
    $scope.newQuestion.hints = []

    $scope.questionToEdit = {}
    $scope.questionToEdit.hints = []

    $scope.compileOutput = ''
    $scope.runOutput = ''

    $scope.showComments = false
    $scope.feedback = ''
    $scope.className = ''
    $scope.readOnlyChecked = false

    /**
      * Toggles the read only value of the starter code for this question.
      * @param {number} index the index of the code editor for this question.
      *                 Use -1 for adding a new question.
      * @return {} fixme
      */
    $scope.toggleReadOnly = function (index) {
      let editor = {}
      let q = {}
      if (index < 0) {
        // use newQuestion
        q = $scope.newQuestion
        editor = $scope.editor
      } else {
        // use questionToEdit
        q = $scope.questionToEdit
        editor = $scope.editors[index]
      }
      if (editor.getReadOnly()) {
        editor.setReadOnly(false)
        q.readOnly = false
      } else {
        editor.setReadOnly(true)
        q.readOnly = true
      }
    }

    /**
     * Determines whether |str| ends with |suffix|.
     * @param {string} str the string to check.
     * @param {string} suffix the suffix to look for in |str|.
     * @return {} fixme
     */
    const endsWith = function (str, suffix) {
      return str.indexOf(suffix, str.length - suffix.length) !== -1
    }

    // |useEditQuestion| - Boolean, whether to use the edit question variable
    const getClassName = function (useEditQuestion) {
      let className = ''
      if (useEditQuestion && typeof ($scope.questionToEdit.className) !== 'undefined') {
        className = $scope.questionToEdit.className
      } else {
        className = $scope.className
      }

      if (endsWith(className, '.c')) {
        className.slice(0, -5)
        return className.slice(0, -5)
      }
      return className
    }

    const getFileName = function (useEditQuestion) {
      let className = ''
      if (useEditQuestion && typeof ($scope.questionToEdit.className) !== 'undefined') {
        className = $scope.questionToEdit.className
      } else {
        className = $scope.className
      }

      if (endsWith(className, '.c')) {
        return className
      }
      return `${className}.c`
    }

    // FIXME: this functionality should be moved into topics service
    // index is the index of the code editor for this question
    // use -1 for adding a new question
    $scope.compileCode = function (index) {
      let editor = {}
      let className = ''
      let fileName = ''
      if (index < 0) { // adding a new question
        editor = $scope.editor
        className = getClassName(false)
        fileName = getFileName(false)
      } else { // editing existing q
        editor = $scope.editors[index]
        className = getClassName(true)
        fileName = getFileName(true)
      }

      console.log('in compile func')
      console.log('heres code:')
      const code = editor.getValue()
      console.log(code)
      const obj = { className,
        fileName,
        code, // editedCode,
        user: Auth.getCurrentUser(),
        questionNum: $scope.questionIndex
      }
      $http.post('api/clis/compile', obj).then((data) => {
        if (data === '') {
          // FIXME how to check if no file was actually compiled?
          $scope.compileOutput += 'Successfully compiled code.\n'
        } else {
          $scope.compileOutput += data
        }
      })
    }

    // FIXME: this functionality should be moved into topics service
    // index is the index of the code editor for this question
    // use -1 for adding a new question
    $scope.runCode = function (index) {
      let fileName = ''
      if (index < 0) { // adding new question
        fileName = getFileName(false)
      } else { // editing existing question
        fileName = getFileName(true)
      }

      const obj = { fileName,
        user: Auth.getCurrentUser()
      }
      $http.post('api/clis/run', obj).then((data) => {
        $scope.runOutput = data
      })
    }

    $scope.editTopic = function () {
      topics.editTopic($scope.topic._id, $scope.topic).then((data) => {
        $scope.topic = data
        $scope.topicsEC.forEach((ea) => {
          if (ea._id === data._id) {
            angular.copy(data, ea)
          }
        })
        const message = 'Topic successfully updated!'
        Flash.create('success', message, 3500, { class: 'flash', id: 'flash-id' }, true)
      })
    }

	$scope.deleteTopic = function(){
		console.log("controller deleteTopic");
		topics.deleteTopic($scope.topic._id).success(function(data) {
			const message = "Successfully deleted topic: " + $scope.topic.title;
			Flash.create('success', message, 3500, {class: 'flash', id: 'flash-id'}, true);
		});
	}

    $scope.addHintToNewQ = function () {
      $scope.newQuestion.hints.push('')
    }

    $scope.deleteHintFromNewQ = function (index) {
      $scope.newQuestion.hints.splice(index, 1)
    }
    // FIXME hints aren't working...
    $scope.addHintToExistingQ = function () {
      $scope.questionToEdit.hints.push('')
    }

    $scope.deleteHintFromExistingQ = function (hintIndex) {
      $scope.questionToEdit.hints.splice(hintIndex, 1)
    }

    $scope.focusEditor = function () {
      $scope.editor.focus()
    }

    $scope.populateEditQForm = function (index) {
      // Set up an editor for the question
      const editor = ace.edit(`editor${index}`)
      // Editor part
      const _session = editor.getSession()
      const _renderer = editor.renderer

    // Options
      _renderer.setShowGutter(true)
      editor.setTheme('ace/theme/tomorrow')
      _session.setMode('ace/mode/c_cpp')
      $scope.editors[index] = editor

      $scope.questionToEdit = $scope.topic.questions[index]
      $scope.editors[index].setValue($scope.questionToEdit.code)
      $scope.compileOutput = ''
      $scope.runOutput = ''
    }

    $scope.isActive = function (id) {
      // this function is dependent on the URL set in topics.js
      return (`/admin/editContent/${id}`) === $location.path()
    }

    $scope.aceLoaded = function (_editor) {
      // Editor part
      const _session = _editor.getSession()
      const _renderer = _editor.renderer

      // Options
      _renderer.setShowGutter(true)
      _editor.setTheme('ace/theme/tomorrow')
      _session.setMode('ace/mode/c_cpp')

      $scope.editor = _editor

      console.log('aceloaded func')
      console.log($scope.editor)
    }

    $scope.addQuestion = function () {
      if ($scope.newQuestion.instructions === '') { return }
      topics.addQuestion($scope.topic._id, {
        instructions: $scope.newQuestion.instructions,
        code: $scope.newQuestion.code,
        className: getClassName(false),
        readOnly: $scope.newQuestion.readOnly,
        expectedOutput: $scope.newQuestion.expectedOutput,
        hints: $scope.newQuestion.hints,
        tags: $scope.newQuestion.tags
      }).then((question) => {
        $scope.topic.questions.push(question)
        const message = 'Question successfully added!'
        Flash.create('success', message, 5000, { class: 'custom-class', id: 'custom-id' }, true)
      })

      $scope.newQuestion = {}
      $scope.newQuestion.hints = []
    }

    // does this automatically propogate to the topic being updated??
    $scope.editQ = function (questionIndex) {
      $scope.questionToEdit.code = $scope.editors[questionIndex].getValue()
      topics.editQuestion($scope.questionToEdit._id, $scope.questionToEdit).then(() => {
          // update scope array of questions?
        $scope.questionToEdit = {}
        $scope.questionToEdit.hints = []
      })
    }

    $scope.deleteQuestion = function (id, index) {
      topics.deleteQuestion($scope.topic.questions[index], $scope.topic._id)
      console.log('deleted q in edit content controller now')
      $scope.topic.questions.splice(index, 1)
    }

    // / trying question reordering http://stackoverflow.com/a/27709541
    $scope.moveQUp = function (index) {
      if (index > -1 && index < $scope.topic.questions.length - 1) {
        const tmp = $scope.topic.questions[index + 1]
        $scope.topic.questions[index + 1] = $scope.topic.questions[index]
        $scope.topic.questions[index] = tmp
      }
    }
    $scope.moveQDown = function (index) {
      if (index > 0 && index < $scope.topic.questions.length) {
        const tmp = $scope.topic.questions[index - 1]
        $scope.topic.questions[index - 1] = $scope.topic.questions[index]
        $scope.topic.questions[index] = tmp
      }
    }
  }
}

EditContentController.$inject = ['$scope', '$http', 'Auth', 'User', 'Topics', 'topic', 'topicPromiseEC', '$location', 'flash']
<commit_msg>Reroute to admin home after deleting topic<commit_after>import angular from 'angular'
import ace from 'angular-ui-ace'

export default class EditContentController {
  constructor ($scope, $http, Auth, User, topics, topic, topicPromiseEC, $location, Flash) {
    $scope.topic = topic.data
    $scope.topicsEC = topicPromiseEC

    $scope.editor = {}
    $scope.editors = []

    $scope.newQuestion = {}
    $scope.newQuestion.hints = []

    $scope.questionToEdit = {}
    $scope.questionToEdit.hints = []

    $scope.compileOutput = ''
    $scope.runOutput = ''

    $scope.showComments = false
    $scope.feedback = ''
    $scope.className = ''
    $scope.readOnlyChecked = false

    /**
      * Toggles the read only value of the starter code for this question.
      * @param {number} index the index of the code editor for this question.
      *                 Use -1 for adding a new question.
      * @return {} fixme
      */
    $scope.toggleReadOnly = function (index) {
      let editor = {}
      let q = {}
      if (index < 0) {
        // use newQuestion
        q = $scope.newQuestion
        editor = $scope.editor
      } else {
        // use questionToEdit
        q = $scope.questionToEdit
        editor = $scope.editors[index]
      }
      if (editor.getReadOnly()) {
        editor.setReadOnly(false)
        q.readOnly = false
      } else {
        editor.setReadOnly(true)
        q.readOnly = true
      }
    }

    /**
     * Determines whether |str| ends with |suffix|.
     * @param {string} str the string to check.
     * @param {string} suffix the suffix to look for in |str|.
     * @return {} fixme
     */
    const endsWith = function (str, suffix) {
      return str.indexOf(suffix, str.length - suffix.length) !== -1
    }

    // |useEditQuestion| - Boolean, whether to use the edit question variable
    const getClassName = function (useEditQuestion) {
      let className = ''
      if (useEditQuestion && typeof ($scope.questionToEdit.className) !== 'undefined') {
        className = $scope.questionToEdit.className
      } else {
        className = $scope.className
      }

      if (endsWith(className, '.c')) {
        className.slice(0, -5)
        return className.slice(0, -5)
      }
      return className
    }

    const getFileName = function (useEditQuestion) {
      let className = ''
      if (useEditQuestion && typeof ($scope.questionToEdit.className) !== 'undefined') {
        className = $scope.questionToEdit.className
      } else {
        className = $scope.className
      }

      if (endsWith(className, '.c')) {
        return className
      }
      return `${className}.c`
    }

    // FIXME: this functionality should be moved into topics service
    // index is the index of the code editor for this question
    // use -1 for adding a new question
    $scope.compileCode = function (index) {
      let editor = {}
      let className = ''
      let fileName = ''
      if (index < 0) { // adding a new question
        editor = $scope.editor
        className = getClassName(false)
        fileName = getFileName(false)
      } else { // editing existing q
        editor = $scope.editors[index]
        className = getClassName(true)
        fileName = getFileName(true)
      }

      console.log('in compile func')
      console.log('heres code:')
      const code = editor.getValue()
      console.log(code)
      const obj = { className,
        fileName,
        code, // editedCode,
        user: Auth.getCurrentUser(),
        questionNum: $scope.questionIndex
      }
      $http.post('api/clis/compile', obj).then((data) => {
        if (data === '') {
          // FIXME how to check if no file was actually compiled?
          $scope.compileOutput += 'Successfully compiled code.\n'
        } else {
          $scope.compileOutput += data
        }
      })
    }

    // FIXME: this functionality should be moved into topics service
    // index is the index of the code editor for this question
    // use -1 for adding a new question
    $scope.runCode = function (index) {
      let fileName = ''
      if (index < 0) { // adding new question
        fileName = getFileName(false)
      } else { // editing existing question
        fileName = getFileName(true)
      }

      const obj = { fileName,
        user: Auth.getCurrentUser()
      }
      $http.post('api/clis/run', obj).then((data) => {
        $scope.runOutput = data
      })
    }

    $scope.editTopic = function () {
      topics.editTopic($scope.topic._id, $scope.topic).then((data) => {
        $scope.topic = data
        $scope.topicsEC.forEach((ea) => {
          if (ea._id === data._id) {
            angular.copy(data, ea)
          }
        })
        const message = 'Topic successfully updated!'
        Flash.create('success', message, 3500, { class: 'flash', id: 'flash-id' }, true)
      })
    }

	$scope.deleteTopic = function(){
		console.log("controller deleteTopic");
		topics.deleteTopic($scope.topic._id).success(function(data) {
			const message = "Successfully deleted topic: " + $scope.topic.title;
			Flash.create('success', message, 1000, {class: 'flash', id: 'flash-id'}, true);
			$location.path('/admin');
		});
	}

    $scope.addHintToNewQ = function () {
      $scope.newQuestion.hints.push('')
    }

    $scope.deleteHintFromNewQ = function (index) {
      $scope.newQuestion.hints.splice(index, 1)
    }
    // FIXME hints aren't working...
    $scope.addHintToExistingQ = function () {
      $scope.questionToEdit.hints.push('')
    }

    $scope.deleteHintFromExistingQ = function (hintIndex) {
      $scope.questionToEdit.hints.splice(hintIndex, 1)
    }

    $scope.focusEditor = function () {
      $scope.editor.focus()
    }

    $scope.populateEditQForm = function (index) {
      // Set up an editor for the question
      const editor = ace.edit(`editor${index}`)
      // Editor part
      const _session = editor.getSession()
      const _renderer = editor.renderer

    // Options
      _renderer.setShowGutter(true)
      editor.setTheme('ace/theme/tomorrow')
      _session.setMode('ace/mode/c_cpp')
      $scope.editors[index] = editor

      $scope.questionToEdit = $scope.topic.questions[index]
      $scope.editors[index].setValue($scope.questionToEdit.code)
      $scope.compileOutput = ''
      $scope.runOutput = ''
    }

    $scope.isActive = function (id) {
      // this function is dependent on the URL set in topics.js
      return (`/admin/editContent/${id}`) === $location.path()
    }

    $scope.aceLoaded = function (_editor) {
      // Editor part
      const _session = _editor.getSession()
      const _renderer = _editor.renderer

      // Options
      _renderer.setShowGutter(true)
      _editor.setTheme('ace/theme/tomorrow')
      _session.setMode('ace/mode/c_cpp')

      $scope.editor = _editor

      console.log('aceloaded func')
      console.log($scope.editor)
    }

    $scope.addQuestion = function () {
      if ($scope.newQuestion.instructions === '') { return }
      topics.addQuestion($scope.topic._id, {
        instructions: $scope.newQuestion.instructions,
        code: $scope.newQuestion.code,
        className: getClassName(false),
        readOnly: $scope.newQuestion.readOnly,
        expectedOutput: $scope.newQuestion.expectedOutput,
        hints: $scope.newQuestion.hints,
        tags: $scope.newQuestion.tags
      }).then((question) => {
        $scope.topic.questions.push(question)
        const message = 'Question successfully added!'
        Flash.create('success', message, 5000, { class: 'custom-class', id: 'custom-id' }, true)
      })

      $scope.newQuestion = {}
      $scope.newQuestion.hints = []
    }

    // does this automatically propogate to the topic being updated??
    $scope.editQ = function (questionIndex) {
      $scope.questionToEdit.code = $scope.editors[questionIndex].getValue()
      topics.editQuestion($scope.questionToEdit._id, $scope.questionToEdit).then(() => {
          // update scope array of questions?
        $scope.questionToEdit = {}
        $scope.questionToEdit.hints = []
      })
    }

    $scope.deleteQuestion = function (id, index) {
      topics.deleteQuestion($scope.topic.questions[index], $scope.topic._id)
      console.log('deleted q in edit content controller now')
      $scope.topic.questions.splice(index, 1)
    }

    // / trying question reordering http://stackoverflow.com/a/27709541
    $scope.moveQUp = function (index) {
      if (index > -1 && index < $scope.topic.questions.length - 1) {
        const tmp = $scope.topic.questions[index + 1]
        $scope.topic.questions[index + 1] = $scope.topic.questions[index]
        $scope.topic.questions[index] = tmp
      }
    }
    $scope.moveQDown = function (index) {
      if (index > 0 && index < $scope.topic.questions.length) {
        const tmp = $scope.topic.questions[index - 1]
        $scope.topic.questions[index - 1] = $scope.topic.questions[index]
        $scope.topic.questions[index] = tmp
      }
    }
  }
}

EditContentController.$inject = ['$scope', '$http', 'Auth', 'User', 'Topics', 'topic', 'topicPromiseEC', '$location', 'flash']
<|endoftext|>


<commit_before>"use strict";

define(['js/PanelBase/PanelBase',
    'js/Widgets/LogLevelManager/LogLevelManagerWidget',
    'js/Widgets/NetworkStatus/NetworkStatusWidget',
    'js/Widgets/BranchStatus/BranchStatusWidget',
    'js/Widgets/BranchSelector/BranchSelectorWidget',
    'js/Widgets/KeyboardManager/KeyboardManagerWidget'], function (PanelBase,
                                                  LogLevelManagerWidget,
                                                  NetworkStatusWidget,
                                                  BranchStatusWidget,
                                                  BranchSelectorWidget,
                                                  KeyboardManagerWidget) {

    var FooterControlsPanel,
        __parent__ = PanelBase;

    FooterControlsPanel = function (layoutManager, params) {
        var options = {};
        //set properties from options
        options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = "FooterControlsPanel";

        //call parent's constructor
        __parent__.apply(this, [options]);

        this._client = params.client;

        //initialize UI
        this._initialize();

        this.logger.debug("FooterControlsPanel ctor finished");
    };

    //inherit from PanelBaseWithHeader
    _.extend(FooterControlsPanel.prototype, __parent__.prototype);

    FooterControlsPanel.prototype._initialize = function () {
        //main container
        var navBar = $('
', {'class': "navbar navbar-inverse navbar-fixed-bottom"});
        var navBarInner = $('
', {'class': "navbar-inner"});
        var separator = $('

');
        var widgetPlaceHolder = $('

');

        navBar.append(navBarInner);
        this.$el.append(navBar);

        //add ISIS link
        var pullLeft = $('

');
        pullLeft.append($('

© 2014 ISIS

'));
        navBarInner.append(pullLeft);

        //add version UI piece
        var pullLeft = $('

');
        pullLeft.append($('

version: ' + WebGMEGlobal.version + '

'));
        navBarInner.append(pullLeft);

        //padding from screen right edge
        navBarInner.append(separator.clone());

        //keyboard enable/disbale widget (NOTE: only on non touch device)
        if (WebGMEGlobal.SUPPORTS_TOUCH !== true) {
            var keyBoardManagerEl = widgetPlaceHolder.clone();
            new KeyboardManagerWidget(keyBoardManagerEl);
            navBarInner.append(keyBoardManagerEl).append(separator.clone());
        }

        var logLevelManagerEl = widgetPlaceHolder.clone();
        new LogLevelManagerWidget(logLevelManagerEl);
        navBarInner.append(logLevelManagerEl).append(separator.clone());

        var networkStatusEl = widgetPlaceHolder.clone();
        new NetworkStatusWidget(networkStatusEl, this._client);
        navBarInner.append(networkStatusEl).append(separator.clone());

        var branchStatusEl = widgetPlaceHolder.clone();
        new BranchStatusWidget(branchStatusEl, this._client);
        navBarInner.append(branchStatusEl).append(separator.clone());

        var branchSelectorEl = widgetPlaceHolder.clone();
        new BranchSelectorWidget(branchSelectorEl, this._client);
        navBarInner.append(branchSelectorEl).append(separator.clone());
    };

    return FooterControlsPanel;
});
<commit_msg>ISIS to Vanderbilt University rename<commit_after>"use strict";

define(['js/PanelBase/PanelBase',
    'js/Widgets/LogLevelManager/LogLevelManagerWidget',
    'js/Widgets/NetworkStatus/NetworkStatusWidget',
    'js/Widgets/BranchStatus/BranchStatusWidget',
    'js/Widgets/BranchSelector/BranchSelectorWidget',
    'js/Widgets/KeyboardManager/KeyboardManagerWidget'], function (PanelBase,
                                                  LogLevelManagerWidget,
                                                  NetworkStatusWidget,
                                                  BranchStatusWidget,
                                                  BranchSelectorWidget,
                                                  KeyboardManagerWidget) {

    var FooterControlsPanel,
        __parent__ = PanelBase;

    FooterControlsPanel = function (layoutManager, params) {
        var options = {};
        //set properties from options
        options[PanelBase.OPTIONS.LOGGER_INSTANCE_NAME] = "FooterControlsPanel";

        //call parent's constructor
        __parent__.apply(this, [options]);

        this._client = params.client;

        //initialize UI
        this._initialize();

        this.logger.debug("FooterControlsPanel ctor finished");
    };

    //inherit from PanelBaseWithHeader
    _.extend(FooterControlsPanel.prototype, __parent__.prototype);

    FooterControlsPanel.prototype._initialize = function () {
        //main container
        var navBar = $('
', {'class': "navbar navbar-inverse navbar-fixed-bottom"});
        var navBarInner = $('
', {'class': "navbar-inner"});
        var separator = $('

');
        var widgetPlaceHolder = $('

');

        navBar.append(navBarInner);
        this.$el.append(navBar);

        //add ISIS link
        var pullLeft = $('

');
        pullLeft.append($('

© 2014 Vanderbilt University

'));
        navBarInner.append(pullLeft);

        //add version UI piece
        var pullLeft = $('

');
        pullLeft.append($('

version: ' + WebGMEGlobal.version + '

'));
        navBarInner.append(pullLeft);

        //padding from screen right edge
        navBarInner.append(separator.clone());

        //keyboard enable/disbale widget (NOTE: only on non touch device)
        if (WebGMEGlobal.SUPPORTS_TOUCH !== true) {
            var keyBoardManagerEl = widgetPlaceHolder.clone();
            new KeyboardManagerWidget(keyBoardManagerEl);
            navBarInner.append(keyBoardManagerEl).append(separator.clone());
        }

        var logLevelManagerEl = widgetPlaceHolder.clone();
        new LogLevelManagerWidget(logLevelManagerEl);
        navBarInner.append(logLevelManagerEl).append(separator.clone());

        var networkStatusEl = widgetPlaceHolder.clone();
        new NetworkStatusWidget(networkStatusEl, this._client);
        navBarInner.append(networkStatusEl).append(separator.clone());

        var branchStatusEl = widgetPlaceHolder.clone();
        new BranchStatusWidget(branchStatusEl, this._client);
        navBarInner.append(branchStatusEl).append(separator.clone());

        var branchSelectorEl = widgetPlaceHolder.clone();
        new BranchSelectorWidget(branchSelectorEl, this._client);
        navBarInner.append(branchSelectorEl).append(separator.clone());
    };

    return FooterControlsPanel;
});
<|endoftext|>


<commit_before>"use strict"
function getTables(callBack) {

  $.ajax({
    method: "GET",
    url: "/api/tables",
    dataType: "json"
  })
  .done(function(data) {
    callback(data)
  })
  .fail(function(error) {
    callback(error);
  });
}

function getWaitList(callback) {

  $.ajax({
    method: "GET",
    url: "/api/waitlist",
    dataType: "json"
  })
  .done(function(data) {
    callback(data)
  })
  .fail(function(error) {
    callback(data)
  });
}

function postTables(postData,callback) {

  $.ajax({
    method: "POST",
    url: "/api/waitlist",
    data: postData,
    dataType: "json"
  })
  .done(function(data){
    callback(data)
  })
  .fail(function(error) {
    callback(error);
  });
}

function getTables(callback) {

  $.ajax({
    method: "GET",
    url: "/",
    dataType: "html"
  })
  .done(function(data) {
    callback();
  })
  .fail(function(error) {
    callback();
  });
}
<commit_msg>fixing route<commit_after>"use strict"
function getTables(callBack) {

  $.ajax({
    method: "GET",
    url: "/api/tables",
    dataType: "json"
  })
  .done(function(data) {
    callback(data)
  })
  .fail(function(error) {
    callback(error);
  });
}

function getTables(callback) {

  $.ajax({
    method: "GET",
    url: "/api/tables",
    dataType: "json"
  })
  .done(function(data) {
    callback(data)
  })
  .fail(function(error) {
    callback(data)
  });
}

function postTables(postData,callback) {

  $.ajax({
    method: "POST",
    url: "/api/tables",
    data: postData,
    dataType: "json"
  })
  .done(function(data){
    callback(data)
  })
  .fail(function(error) {
    callback(error);
  });
}

function getWaitlist(callback) {

  $.ajax({
    method: "GET",
    url: "/",
    dataType: "html"
  })
  .done(function(data) {
    callback();
  })
  .fail(function(error) {
    callback();
  });
}
<|endoftext|>


<commit_before>/**
 * @class Projects a 3D point in an axonometric scene onto a plane and returns a 2D point.
 * @author matthew@wagerfield.com (Matthew Wagerfield)
 * @constructor
 *
 * @param {Number} pitch The pitch angle of the scene in degrees.
 * @param {Number} rotation The rotation angle of the scene in degrees.
 */
AxonometricProjection = function(pitch, rotation) {

    /**
     * The origin offset of the world coordinate system.
     * @type {Object}
     */
    this._origin = {x: 0, y: 0};

    /**
     * The rotation angle of the scene in radians.
     * @type {Number}
     */
    this._rotationAngle = 0;

    /**
     * The pitch angle of the scene in radians.
     * @type {Number}
     */
    this._pitchAngle = 0;

    /**
     * The pitch ratio of the scene.
     * @type {Number}
     */
    this._pitchRatio = 0;

    /**
     * The z ratio of the scene.
     * @type {Number}
     */
    this._zRatio = 0;

    /**
     * Set the pitch of the scene.
     */
    this.pitch((pitch !== null && pitch !== undefined) ? pitch : 35);

    /**
     * Set the rotation of the scene.
     */
    this.rotate((rotation !== null && rotation !== undefined) ? rotation : 45);
};

AxonometricProjection.prototype = {

    /**
     * Converts degrees to radians.
     * @this {AxonometricProjection}
     *
     * @param {Number} degrees Angle in degrees to convert.
     *
     * @return {Number} Converted angle in radians.
     */
    degreesToRadians: function(degrees) {

        return degrees * Math.PI / 180;
    },

    /**
     * Converts radians to degrees.
     * @this {AxonometricProjection}
     *
     * @param {Number} radians Angle in radians to convert.
     *
     * @return {Number} Converted angle in degrees.
     */
    radiansToDegrees: function(radians) {

        return radians * 180 / Math.PI;
    },

    /**
     * Sets the origin offset of the world coordinate system.
     * @this {AxonometricProjection}
     *
     * @param {Number} x The x offset of the coordinate system.
     * @param {Number} y The y offset of the coordinate system.
     *
     * @return {Object} The origin of the world coordinate system.
     */
    origin: function(x, y) {

        if (x !== null && x !== undefined) {

            this._origin.x = x;
        }
        if (y !== null && y !== undefined) {

            this._origin.y = y;
        }

        return this._origin;
    },

    /**
     * Sets the pitch of the scene in degrees.
     * @this {AxonometricProjection}
     *
     * @param {Number} degrees The angle to pitch the scene to.
     *
     * @return {Number} The pitch of the scene in degrees.
     */
    pitch: function(degrees) {

        if (degrees !== null && degrees !== undefined) {

            var sine = Math.sin(this.degreesToRadians(degrees));
            var sign = sine / (sine ? Math.abs(sine) : 1);
            var modulo = Math.abs(degrees) % 180 - 90;
            var slope = (modulo > 0 ? 90 - modulo : 90 + modulo);
            var angle = slope * sign;
            var radians = this.degreesToRadians(angle);

            this._pitchAngle = angle;
            this._pitchRatio = Math.sin(radians);
            this._zRatio = Math.cos(radians);
        }

        return this._pitchAngle;
    },

    /**
     * Sets the rotation of the scene in degrees.
     * @this {AxonometricProjection}
     *
     * @param {Number} degrees The angle to rotate the scene to.
     *
     * @return {Number} The rotation of the scene in radians.
     */
    rotate: function(degrees) {

        if (degrees !== null && degrees !== undefined) {

            this._rotationAngle = this.degreesToRadians(-degrees);
        }

        return this._rotationAngle;
    },

    /**
     * Projects a 3D point onto a plane and returnd the 2D point coordinate.
     * @this {AxonometricProjection}
     *
     * @param {Number} x The x position of the point.
     * @param {Number} y The y position of the point.
     * @param {Number} z The z position of the point.
     *
     * @return {Object} 2D point coordinate.
     */
    project: function(x, y, z) {

        var point = {x: 0, y: 0};

        // x offset
        point.x += x * Math.cos(this._rotationAngle);
        point.y += x * Math.sin(this._rotationAngle);

        // y offset
        point.x -= y * Math.sin(this._rotationAngle);
        point.y += y * Math.cos(this._rotationAngle);

        // pitch offset
        point.y *= this._pitchRatio;

        // z offset
        point.y -= z * this._zRatio;

        // origin offset
        point.x += this._origin.x;
        point.y += this._origin.y;

        return point;
    }
};

// Assign AP to AxonometricProjection for convenience.
AP = AxonometricProjection;<commit_msg>Added MIT license.<commit_after>/**
 * @class Projects a 3D point in an axonometric scene onto a plane and returns a 2D point.
 * @author matthew@wagerfield.com (Matthew Wagerfield)
 * @constructor
 *
 * @param {Number} pitch The pitch angle of the scene in degrees.
 * @param {Number} rotation The rotation angle of the scene in degrees.
 */
AxonometricProjection = function(pitch, rotation) {

    /**
     * The origin offset of the world coordinate system.
     * @type {Object}
     */
    this._origin = {x: 0, y: 0};

    /**
     * The rotation angle of the scene in radians.
     * @type {Number}
     */
    this._rotationAngle = 0;

    /**
     * The pitch angle of the scene in radians.
     * @type {Number}
     */
    this._pitchAngle = 0;

    /**
     * The pitch ratio of the scene.
     * @type {Number}
     */
    this._pitchRatio = 0;

    /**
     * The z ratio of the scene.
     * @type {Number}
     */
    this._zRatio = 0;

    /**
     * Set the pitch of the scene.
     */
    this.pitch((pitch !== null && pitch !== undefined) ? pitch : 35);

    /**
     * Set the rotation of the scene.
     */
    this.rotate((rotation !== null && rotation !== undefined) ? rotation : 45);
};

AxonometricProjection.prototype = {

    /**
     * Converts degrees to radians.
     * @this {AxonometricProjection}
     *
     * @param {Number} degrees Angle in degrees to convert.
     *
     * @return {Number} Converted angle in radians.
     */
    degreesToRadians: function(degrees) {

        return degrees * Math.PI / 180;
    },

    /**
     * Converts radians to degrees.
     * @this {AxonometricProjection}
     *
     * @param {Number} radians Angle in radians to convert.
     *
     * @return {Number} Converted angle in degrees.
     */
    radiansToDegrees: function(radians) {

        return radians * 180 / Math.PI;
    },

    /**
     * Sets the origin offset of the world coordinate system.
     * @this {AxonometricProjection}
     *
     * @param {Number} x The x offset of the coordinate system.
     * @param {Number} y The y offset of the coordinate system.
     *
     * @return {Object} The origin of the world coordinate system.
     */
    origin: function(x, y) {

        if (x !== null && x !== undefined) {

            this._origin.x = x;
        }
        if (y !== null && y !== undefined) {

            this._origin.y = y;
        }

        return this._origin;
    },

    /**
     * Sets the pitch of the scene in degrees.
     * @this {AxonometricProjection}
     *
     * @param {Number} degrees The angle to pitch the scene to.
     *
     * @return {Number} The pitch of the scene in degrees.
     */
    pitch: function(degrees) {

        if (degrees !== null && degrees !== undefined) {

            var sine = Math.sin(this.degreesToRadians(degrees));
            var sign = sine / (sine ? Math.abs(sine) : 1);
            var modulo = Math.abs(degrees) % 180 - 90;
            var slope = (modulo > 0 ? 90 - modulo : 90 + modulo);
            var angle = slope * sign;
            var radians = this.degreesToRadians(angle);

            this._pitchAngle = angle;
            this._pitchRatio = Math.sin(radians);
            this._zRatio = Math.cos(radians);
        }

        return this._pitchAngle;
    },

    /**
     * Sets the rotation of the scene in degrees.
     * @this {AxonometricProjection}
     *
     * @param {Number} degrees The angle to rotate the scene to.
     *
     * @return {Number} The rotation of the scene in radians.
     */
    rotate: function(degrees) {

        if (degrees !== null && degrees !== undefined) {

            this._rotationAngle = this.degreesToRadians(-degrees);
        }

        return this._rotationAngle;
    },

    /**
     * Projects a 3D point onto a plane and returnd the 2D point coordinate.
     * @this {AxonometricProjection}
     *
     * @param {Number} x The x position of the point.
     * @param {Number} y The y position of the point.
     * @param {Number} z The z position of the point.
     *
     * @return {Object} 2D point coordinate.
     */
    project: function(x, y, z) {

        var point = {x: 0, y: 0};

        // x offset
        point.x += x * Math.cos(this._rotationAngle);
        point.y += x * Math.sin(this._rotationAngle);

        // y offset
        point.x -= y * Math.sin(this._rotationAngle);
        point.y += y * Math.cos(this._rotationAngle);

        // pitch offset
        point.y *= this._pitchRatio;

        // z offset
        point.y -= z * this._zRatio;

        // origin offset
        point.x += this._origin.x;
        point.y += this._origin.y;

        return point;
    }
};

// Assign AP to AxonometricProjection for convenience.
AP = AxonometricProjection;

//============================================================
//
// Copyright (c) 2012 Matthew Wagerfield
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
// OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.
//
//============================================================<|endoftext|>


<commit_before>Mealpler.directive('datePicker', function () {
    const link = (scope, el, attrs, controller) => {
        const weekCtrl = controller;
        const dateCtrl = scope.dateCtrl;

        dateCtrl.datePickerTarget = $('#' + attrs.name);
        dateCtrl.datePickerTarget.daterangepicker({
            "locale": dateCtrl.getLocalization(),
            "singleDatePicker": !attrs.single,
            "showDropdowns": true,
            "startDate": weekCtrl.weekStartDate
        }, (start, end, label) => {
            if (attrs.refreshFridge) {

            }
            weekCtrl.init(start);
            scope.$apply();
        });

    };

    return {
        restrict: 'C',
        transclude: true,
        scope: {
            single: '=',
            refreshFridge: '=',
            name: '='
        },
        require: '^^weekManager',
        controller: 'DatePickerCtrl',
        controllerAs: 'dateCtrl',
        link: link
    };
});<commit_msg>MP-29: added for datepicker directive new methods for shoplist daterangepicker<commit_after>Mealpler.directive('datePicker', function () {
    const link = (scope, el, attrs, controller) => {
        const dashboardCtrl = controller;
        const dateCtrl = scope.dateCtrl;
        const startDate = dashboardCtrl.getWeekStartDate();

        dateCtrl.datePickerTarget = $('#' + attrs.name);
        dateCtrl.datePickerTarget.daterangepicker({
            "locale": dateCtrl.getLocalization(),
            "singleDatePicker": !!attrs.single,
            "showDropdowns": true,
            "startDate": startDate
        }, (start, end, label) => {

            //refresh week only from directive placed in week tmpl
            if (!!attrs.refreshWeek) {
                dashboardCtrl.refreshMealDataForWeek(start);
            }

            //fridge needs to be refreshed in both date pickers, but this check is still needed in case I'll decide to remove this logic etc.
            if (!!attrs.refreshFridge) {
                if (!!attrs.single) {
                    //if one date is chosen
                    const startOfWeek = start.startOf('week');
                    dashboardCtrl.refreshShopList(startOfWeek, dashboardCtrl.defaultWeekDuration);
                } else {
                    let duration = end.diff(start, 'days');
                    dashboardCtrl.refreshShopList(start, duration);
                }
            }
            scope.$apply();
        });

    };

    return {
        restrict: 'C',
        transclude: true,
        scope: {
            single: '=',
            refreshFridge: '=',
            name: '=',
            refreshWeek: '='
        },
        require: '^^dashboard',
        controller: 'DatePickerCtrl',
        controllerAs: 'dateCtrl',
        link: link
    };
});<|endoftext|>


<commit_before>// Utility methods for relative time ago

Date.months = I18n.translations.date.month_names.compact();
Date.weekdays = I18n.translations.calendar.abbr_weekdays;
Date.firstDayOfWeek = "sunday";

document.on("dom:loaded", function() {
  if(!my_user) { return; }
  Date.firstDayOfWeek = my_user.first_day_of_week;
  if(Date.firstDayOfWeek == "monday") {
    Date.weekdays.push(Date.weekdays.shift());
  }
});

_translations = $w("OK Now Today Clear").collect(function(w) {
  return I18n.translations.calendar[w.toLowerCase()];
});

Object.extend(Date.prototype, {
  beginning_of_day: function() {
    var date = new Date(this);
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    return date;
  },
  // Renders date with custom formatting, similar to Ruby's strftime
  strftime: function(format) {
    var minutes = this.getMinutes(),
        hours = this.getHours(),
        day = this.getDay(),
        month = this.getMonth(),
        t = I18n.translations;

    function pad(num) { return num.toPaddedString(2); }

    return format.gsub(/\%([aAbBcdDHiImMpSwyY])/, function(part) {
      switch(part[1]) {
        case 'a': return t.date.abbr_day_names[day];
        case 'A': return t.date.day_names[day];
        case 'b': return t.date.abbr_month_names[month+1];
        case 'B': return t.date.month_names[month+1];
        case 'c': return this.strftime("%a %b %d %H:%M:%S %Y");
        case 'd': return this.getDate();
        case 'D': return pad(this.getDate());
        case 'H': return pad(hours);
        case 'i': return (hours === 12 || hours === 0) ? 12 : (hours + 12) % 12;
        case 'I': return pad((hours === 12 || hours === 0) ? 12 : (hours + 12) % 12);
        case 'm': return pad(month + 1);
        case 'M': return pad(minutes);
        case 'p': return hours > 11 ? t.time.pm : t.time.am;
        case 'S': return pad(this.getSeconds());
        case 'w': return day;
        case 'y': return pad(this.getFullYear() % 100);
        case 'Y': return this.getFullYear().toString();
      }
    }.bind(this));
  },
  // Will parse date and give its relative distance in words to
  // current_date (which defaults to now)
  timeAgo: function(current_date) {
    current_date = current_date || new Date();

    var posted_date = new Date(this);
    var elapsed = current_date - posted_date;

    var minutes = Math.floor(elapsed / (1000 * 60));
    var days = Math.floor(elapsed / (1000 * 60 * 60 * 24));
    var today = (current_date.getDay() === posted_date.getDay() && days < 2);
    var t = I18n.translations;

    if (elapsed < 0) {
      return posted_date.strftime(t.date.formats.long); }
    else if (minutes === 0) {
      return t.datetime.distance_in_words.now; }
    else if (minutes == 1) {
      return t.datetime.time_ago.gsub("%{time_ago_in_words}", t.datetime.distance_in_words.x_minutes.one); }
    else if (minutes < 60) {
      return t.datetime.time_ago.gsub("%{time_ago_in_words}", t.datetime.distance_in_words.x_minutes.other.gsub("%{count}", minutes)); }
    else if (today) {
      return posted_date.strftime(t.time.formats.short); }
    else if (days == 1) {
      return t.date.yesterday + ' ' + posted_date.strftime(t.time.formats.short); }
    else if (days <= 14) {
      return posted_date.strftime("%a " + t.date.formats.short); }
    else if (current_date.getFullYear() == posted_date.getFullYear()) {
      return posted_date.strftime(t.date.formats.short);
    }
    else { return posted_date.strftime(t.date.formats.long); }
  }
});

// Replaces all the cache-friendly static dates
// with relative time ago in words
Date.format_posted_dates = function() {
  $$('time.timeago').each(function(c){
    var date = new Date(parseInt(c.readAttribute('data-msec')));
    c.update(date.timeAgo());
  });
};

document.on("dom:loaded", function() {
  Date.format_posted_dates();
  new PeriodicalExecuter(Date.format_posted_dates, 30);
});

document.on("ajax:success", function() {
  Date.format_posted_dates.defer();
});

<commit_msg>CalendarDateSelect needs an object not an array for _translations<commit_after>// Utility methods for relative time ago

Date.months = I18n.translations.date.month_names.compact();
Date.weekdays = I18n.translations.calendar.abbr_weekdays;
Date.firstDayOfWeek = "sunday";

document.on("dom:loaded", function() {
  if(!my_user) { return; }
  Date.firstDayOfWeek = my_user.first_day_of_week;
  if(Date.firstDayOfWeek == "monday") {
    Date.weekdays.push(Date.weekdays.shift());
  }
});

_translations = $w("OK Now Today Clear").inject({}, function(h, w) {
  h[w] = I18n.translations.calendar[w.toLowerCase()];
  return h;
});

Object.extend(Date.prototype, {
  beginning_of_day: function() {
    var date = new Date(this);
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    return date;
  },
  // Renders date with custom formatting, similar to Ruby's strftime
  strftime: function(format) {
    var minutes = this.getMinutes(),
        hours = this.getHours(),
        day = this.getDay(),
        month = this.getMonth(),
        t = I18n.translations;

    function pad(num) { return num.toPaddedString(2); }

    return format.gsub(/\%([aAbBcdDHiImMpSwyY])/, function(part) {
      switch(part[1]) {
        case 'a': return t.date.abbr_day_names[day];
        case 'A': return t.date.day_names[day];
        case 'b': return t.date.abbr_month_names[month+1];
        case 'B': return t.date.month_names[month+1];
        case 'c': return this.strftime("%a %b %d %H:%M:%S %Y");
        case 'd': return this.getDate();
        case 'D': return pad(this.getDate());
        case 'H': return pad(hours);
        case 'i': return (hours === 12 || hours === 0) ? 12 : (hours + 12) % 12;
        case 'I': return pad((hours === 12 || hours === 0) ? 12 : (hours + 12) % 12);
        case 'm': return pad(month + 1);
        case 'M': return pad(minutes);
        case 'p': return hours > 11 ? t.time.pm : t.time.am;
        case 'S': return pad(this.getSeconds());
        case 'w': return day;
        case 'y': return pad(this.getFullYear() % 100);
        case 'Y': return this.getFullYear().toString();
      }
    }.bind(this));
  },
  // Will parse date and give its relative distance in words to
  // current_date (which defaults to now)
  timeAgo: function(current_date) {
    current_date = current_date || new Date();

    var posted_date = new Date(this);
    var elapsed = current_date - posted_date;

    var minutes = Math.floor(elapsed / (1000 * 60));
    var days = Math.floor(elapsed / (1000 * 60 * 60 * 24));
    var today = (current_date.getDay() === posted_date.getDay() && days < 2);
    var t = I18n.translations;

    if (elapsed < 0) {
      return posted_date.strftime(t.date.formats.long); }
    else if (minutes === 0) {
      return t.datetime.distance_in_words.now; }
    else if (minutes == 1) {
      return t.datetime.time_ago.gsub("%{time_ago_in_words}", t.datetime.distance_in_words.x_minutes.one); }
    else if (minutes < 60) {
      return t.datetime.time_ago.gsub("%{time_ago_in_words}", t.datetime.distance_in_words.x_minutes.other.gsub("%{count}", minutes)); }
    else if (today) {
      return posted_date.strftime(t.time.formats.short); }
    else if (days == 1) {
      return t.date.yesterday + ' ' + posted_date.strftime(t.time.formats.short); }
    else if (days <= 14) {
      return posted_date.strftime("%a " + t.date.formats.short); }
    else if (current_date.getFullYear() == posted_date.getFullYear()) {
      return posted_date.strftime(t.date.formats.short);
    }
    else { return posted_date.strftime(t.date.formats.long); }
  }
});

// Replaces all the cache-friendly static dates
// with relative time ago in words
Date.format_posted_dates = function() {
  $$('time.timeago').each(function(c){
    var date = new Date(parseInt(c.readAttribute('data-msec')));
    c.update(date.timeAgo());
  });
};

document.on("dom:loaded", function() {
  Date.format_posted_dates();
  new PeriodicalExecuter(Date.format_posted_dates, 30);
});

document.on("ajax:success", function() {
  Date.format_posted_dates.defer();
});

<|endoftext|>


<commit_before>define([
  'angular',
  'moment',
  'text!./cam-tasklist-tasks.html'
], function(
  angular,
  moment,
  template
) {
  'use strict';

  function indexOfId(items, id) {
    for (var i in items) {
      if (items[i].id === id) { return i; }
    }
    return -1;
  }

  function itemById(items, id) {
    var index = indexOfId(items, id);
    if (index > -1) {
      return items[index];
    }
  }

  function fixReadDateTimezone(dateStr) {
    if (!dateStr) { return dateStr; }
    var d = new Date(dateStr);
    return (new Date(d.getTime() + (d.getTimezoneOffset() * 60 * 1000))).toJSON();
  }

  function fixWriteDateTimezone(dateObj) {
    return new Date(dateObj.getTime() - (dateObj.getTimezoneOffset() * 1000 * 60));
  }

  return [
    '$modal',
    '$location',
    '$rootScope',
    '$q',
    'camAPI',
  function(
    $modal,
    $location,
    $rootScope,
    $q,
    camAPI
  ) {
    var Task = camAPI.resource('task');
    var Filter = camAPI.resource('filter');

    return {
      scope: {
        filter: '='
      },

      template: template,

      link: function(scope) {
        var dateExp = /(Before|After)$/;

        scope.pageSize = 15;
        scope.pageNum = 1;
        scope.totalItems = 0;

        scope.now = new Date();

        scope.loading = false;

        scope.tasks = scope.tasks || [];

        scope.filter = scope.filter || $rootScope.currentFilter;

        scope.sorting = angular.element('[cam-sorting-choices]').scope();

        scope.sorting.$on('sorting.by.change', loadTasks);

        scope.sorting.$on('sorting.order.change', loadTasks);

        function authed() {
          return $rootScope.authentication &&
                  !!$rootScope.authentication.name;
        }

        function setCurrentTask(task, silent) {
          $rootScope.currentTask = task;
          if (!silent) {
            // if there's a task, we pass its ID to the URL,
            // otherwise we clear the URL
            $location.search(task ? {
              task: task.id
            } : {});

            $rootScope.$broadcast('tasklist.task.current');
          }
        }

        function loadTasks() {
          if (!authed() || !scope.filter) { return; }

          scope.loading = true;
          scope.tasks = [];

          var where = buildWhere(scope.sorting.order, scope.sorting.by);

          Filter.getTasks(where, function(err, res) {
            scope.loading = false;
            if (err) { throw err; }

            scope.totalItems = res.count;
            scope.processDefinitions = scope.processDefinitions || [];

            angular.forEach(res._embedded ? res._embedded.processDefinition : [], function(procDef) {
              if (indexOfId(scope.processDefinitions) === -1) {
                scope.processDefinitions.push(procDef);
              }
            });

            angular.forEach(res._embedded.task, function(task, t) {
              // res._embedded.task[t]._serverDue = task.due;
              // res._embedded.task[t]._serverFollowUp = task.followUp;

              res._embedded.task[t].due = fixReadDateTimezone(task.due);
              res._embedded.task[t].followUp = fixReadDateTimezone(task.followUp);

              // console.info('fix dates', res._embedded.task[t]._serverDue, res._embedded.task[t].due);
            });

            scope.tasks = res._embedded.task;
          });
        }

        function buildWhere(order, by) {
          var where = {
            id: scope.filter.id
          };

          where.firstResult = (scope.pageNum - 1) * scope.pageSize;
          where.maxResults = scope.pageSize;

          if (order && by) {
            where.sortBy = by;
            where.sortOrder = order;
          }

          return where;
        }

        scope.pageChange = loadTasks;

        // scope.lookupTask = function(val) {
        //   var deferred = $q.defer();

        //   scope.loading = true;

        //   var where = buildWhere(scope.sorting.order, scope.sorting.by);

        //   where.nameLike = '%'+ val +'%';

        //   Task.list(where, function(err, res) {
        //     scope.loading = false;

        //     if (err) {
        //       return deferred.reject(err);
        //     }

        //     deferred.resolve(res._embedded.tasks);
        //   });

        //   return deferred.promise;
        // };

        // scope.selectedTask = function($item) {
        //   setCurrentTask($item);
        //   scope.searchTask = '';
        // };

        function saveDate(propName) {
          return function(inlineFieldScope) {
            var self = this;
            var task = angular.copy(self.task);

            task[propName] = fixWriteDateTimezone(inlineFieldScope.varValue);
            // task[propName] = inlineFieldScope.varValue;

            delete task._embedded;
            delete task._links;

            Task.update(task, function(err, result) {
              if (err) {
                throw err;
              }

              // scope.$emit('tasklist.task.'+ propName);

              loadTasks();
            });
          };
        }

        scope.saveFollowUpDate = saveDate('followUp');
        scope.saveDueDate = saveDate('due');

        scope.focus = function(delta) {
          setCurrentTask(scope.tasks[delta], true);
        };

        scope.$on('tasklist.process.start', loadTasks);

        scope.$on('tasklist.filter.current', function() {
          if (scope.filter && $rootScope.currentFilter) {
            if (scope.filter.id !== $rootScope.currentFilter.id) {
              scope.filter = $rootScope.currentFilter;
              loadTasks();
            }
          }
          else if ($rootScope.currentFilter) {
            scope.filter = $rootScope.currentFilter;
            loadTasks();
          }
        });

        scope.$on('tasklist.task.update', loadTasks);

        scope.$on('tasklist.task.complete', function() {
          setCurrentTask(null);
        });

        scope.$on('filter.saved', loadTasks);
      }
    };
  }];
});
<commit_msg>fix(tasks): reload tasks when a filter is changed<commit_after>define([
  'angular',
  'moment',
  'text!./cam-tasklist-tasks.html'
], function(
  angular,
  moment,
  template
) {
  'use strict';

  function indexOfId(items, id) {
    for (var i in items) {
      if (items[i].id === id) { return i; }
    }
    return -1;
  }

  function itemById(items, id) {
    var index = indexOfId(items, id);
    if (index > -1) {
      return items[index];
    }
  }

  function fixReadDateTimezone(dateStr) {
    if (!dateStr) { return dateStr; }
    var d = new Date(dateStr);
    return (new Date(d.getTime() + (d.getTimezoneOffset() * 60 * 1000))).toJSON();
  }

  function fixWriteDateTimezone(dateObj) {
    return new Date(dateObj.getTime() - (dateObj.getTimezoneOffset() * 1000 * 60));
  }

  return [
    '$modal',
    '$location',
    '$rootScope',
    '$q',
    'camAPI',
  function(
    $modal,
    $location,
    $rootScope,
    $q,
    camAPI
  ) {
    var Task = camAPI.resource('task');
    var Filter = camAPI.resource('filter');

    return {
      scope: {
        filter: '='
      },

      template: template,

      link: function(scope) {
        var dateExp = /(Before|After)$/;

        scope.pageSize = 15;
        scope.pageNum = 1;
        scope.totalItems = 0;

        scope.now = new Date();

        scope.loading = false;

        scope.tasks = scope.tasks || [];

        scope.filter = scope.filter || $rootScope.currentFilter;

        scope.sorting = angular.element('[cam-sorting-choices]').scope();

        scope.sorting.$on('sorting.by.change', loadTasks);

        scope.sorting.$on('sorting.order.change', loadTasks);

        function authed() {
          return $rootScope.authentication &&
                  !!$rootScope.authentication.name;
        }

        function setCurrentTask(task, silent) {
          $rootScope.currentTask = task;
          if (!silent) {
            // if there's a task, we pass its ID to the URL,
            // otherwise we clear the URL
            $location.search(task ? {
              task: task.id
            } : {});

            $rootScope.$broadcast('tasklist.task.current');
          }
        }

        function loadTasks() {
          if (!authed() || !scope.filter) { return; }

          scope.loading = true;
          scope.tasks = [];

          var where = buildWhere(scope.sorting.order, scope.sorting.by);

          Filter.getTasks(where, function(err, res) {
            scope.loading = false;
            if (err) { throw err; }

            scope.totalItems = res.count;
            scope.processDefinitions = scope.processDefinitions || [];

            angular.forEach(res._embedded ? res._embedded.processDefinition : [], function(procDef) {
              if (indexOfId(scope.processDefinitions) === -1) {
                scope.processDefinitions.push(procDef);
              }
            });

            angular.forEach(res._embedded.task, function(task, t) {
              // res._embedded.task[t]._serverDue = task.due;
              // res._embedded.task[t]._serverFollowUp = task.followUp;

              res._embedded.task[t].due = fixReadDateTimezone(task.due);
              res._embedded.task[t].followUp = fixReadDateTimezone(task.followUp);

              // console.info('fix dates', res._embedded.task[t]._serverDue, res._embedded.task[t].due);
            });

            scope.tasks = res._embedded.task;
          });
        }

        function buildWhere(order, by) {
          var where = {
            id: scope.filter.id
          };

          where.firstResult = (scope.pageNum - 1) * scope.pageSize;
          where.maxResults = scope.pageSize;

          if (order && by) {
            where.sortBy = by;
            where.sortOrder = order;
          }

          return where;
        }

        scope.pageChange = loadTasks;

        // scope.lookupTask = function(val) {
        //   var deferred = $q.defer();

        //   scope.loading = true;

        //   var where = buildWhere(scope.sorting.order, scope.sorting.by);

        //   where.nameLike = '%'+ val +'%';

        //   Task.list(where, function(err, res) {
        //     scope.loading = false;

        //     if (err) {
        //       return deferred.reject(err);
        //     }

        //     deferred.resolve(res._embedded.tasks);
        //   });

        //   return deferred.promise;
        // };

        // scope.selectedTask = function($item) {
        //   setCurrentTask($item);
        //   scope.searchTask = '';
        // };

        function saveDate(propName) {
          return function(inlineFieldScope) {
            var self = this;
            var task = angular.copy(self.task);

            task[propName] = fixWriteDateTimezone(inlineFieldScope.varValue);
            // task[propName] = inlineFieldScope.varValue;

            delete task._embedded;
            delete task._links;

            Task.update(task, function(err, result) {
              if (err) {
                throw err;
              }

              // scope.$emit('tasklist.task.'+ propName);

              loadTasks();
            });
          };
        }

        scope.saveFollowUpDate = saveDate('followUp');
        scope.saveDueDate = saveDate('due');

        scope.focus = function(delta) {
          setCurrentTask(scope.tasks[delta], true);
        };

        scope.$on('tasklist.process.start', loadTasks);

        scope.$on('tasklist.filter.current', function() {
          if (scope.filter && $rootScope.currentFilter) {
            if (scope.filter.id !== $rootScope.currentFilter.id) {
              scope.filter = $rootScope.currentFilter;
              loadTasks();
            }
          }
          else if ($rootScope.currentFilter) {
            scope.filter = $rootScope.currentFilter;
            loadTasks();
          }
        });

        scope.$on('tasklist.task.update', loadTasks);

        scope.$on('tasklist.task.complete', function() {
          setCurrentTask(null);
        });

        $rootScope.$on('filter.deleted', loadTasks);

        $rootScope.$on('filter.saved', loadTasks);
      }
    };
  }];
});
<|endoftext|>


<commit_before>/**
	_moon.ObjectActionDecorator_ is a decorator that wraps a spotlightable object.
	When the object is focused, additional controls are displayed, allowing the
	user to act on the object.

	The decorator supports two orientations: vertical, with object actions placed
	below the wrapped	components, and horizontal, with object actions placed next
	to the components.

	Here's a vertical example:

			{
				kind: "moon.ObjectActionDecorator",
				orientation: "vertical",
				components: [
					{kind: "moon.Item", components: [
						{name: 'image', kind: 'enyo.Image', src: "assets/default-music.png"}
					]}
				],
				actionComponents: [
					{kind: "moon.Button", name: "Play", small: true, content: "PLAY"},
					{kind: "moon.Button", name: "Favorite", small: true, content: "FAVORITE"},
					{kind: "moon.Button", name: "Share", small: true, content: "SHARE"}
				]
			}

*/
enyo.kind({
	name: "moon.ObjectActionDecorator",
	//* @protected
	classes: "moon-objaction",
	handlers: {
		onSpotlightFocus: "spotFocused",
		onSpotlightBlur: "spotBlur",
		onenter: "enter",
		onleave: "leave"
	},
	//* @public
	published: {
		/**
			Orientation of object actions in relation to focused components.
			_vertical_ places the object actions below the components, while
			_horizontal_ places them next to the components.
		*/
		orientation: 'vertical',
		/**
			When _orientation_ is _vertical_, setting _noStretch: true_ causes the
			object actions to be stretched to fit the width of the components above.
		*/
		noStretch: false
	},
	//* @protected
	components: [
		{name:"client", classes: "moon-objaction-client"},
		{name:"actions", classes: "moon-objaction-actions"}
	],
	//*@protected
	orientationChanged: function () {
		var vertical = this.getOrientation() == "vertical";
		this.addRemoveClass("vertical", vertical);
		this.addRemoveClass("horizontal", !vertical);
		this.$.actions.addRemoveClass("moon-vspacing", vertical);
		this.$.actions.addRemoveClass("moon-hspacing", !vertical);
	},
	noStretchChanged: function() {
		this.$.actions.addRemoveClass("stretch", !this.noStretch);
	},
	initComponents: function() {
		this.inherited(arguments);
		if (this.actionComponents) {
			var owner = this.hasOwnProperty("actionComponents") ? this.getInstanceOwner() : this;
			this.$.actions.createComponents(this.actionComponents, {owner: owner});
		}
		this.orientationChanged();
		this.noStretchChanged();
	},
	spotFocused: function(inSender, inEvent) {
		this.focused = true;
		this.updateActionsVisibility();
	},
	spotBlur: function(inSender, inEvent) {
		this.focused = false;
		this.entered = false;
		this.updateActionsVisibility();
	},
	enter: function(inSender, inEvent) {
		this.entered = true;
		this.updateActionsVisibility();
	},
	leave: function(inSender, inEvent) {
		this.entered = false;
		this.updateActionsVisibility();
	},
	updateActionsVisibility: function() {
		this.$.actions.applyStyle("opacity", (this.focused || this.entered) ? 1 : 0);
	}
});<commit_msg>Changing to Unix line endings<commit_after>/**
	_moon.ObjectActionDecorator_ is a decorator that wraps a spotlightable object.
	When the object is focused, additional controls are displayed, allowing the
	user to act on the object.

	The decorator supports two orientations: vertical, with object actions placed
	below the wrapped	components, and horizontal, with object actions placed next
	to the components.

	Here's a vertical example:

			{
				kind: "moon.ObjectActionDecorator",
				orientation: "vertical",
				components: [
					{kind: "moon.Item", components: [
						{name: 'image', kind: 'enyo.Image', src: "assets/default-music.png"}
					]}
				],
				actionComponents: [
					{kind: "moon.Button", name: "Play", small: true, content: "PLAY"},
					{kind: "moon.Button", name: "Favorite", small: true, content: "FAVORITE"},
					{kind: "moon.Button", name: "Share", small: true, content: "SHARE"}
				]
			}

*/
enyo.kind({
	name: "moon.ObjectActionDecorator",
	//* @protected
	classes: "moon-objaction",
	handlers: {
		onSpotlightFocus: "spotFocused",
		onSpotlightBlur: "spotBlur",
		onenter: "enter",
		onleave: "leave"
	},
	//* @public
	published: {
		/**
			Orientation of object actions in relation to focused components.
			_vertical_ places the object actions below the components, while
			_horizontal_ places them next to the components.
		*/
		orientation: 'vertical',
		/**
			When _orientation_ is _vertical_, setting _noStretch: true_ causes the
			object actions to be stretched to fit the width of the components above.
		*/
		noStretch: false
	},
	//* @protected
	components: [
		{name:"client", classes: "moon-objaction-client"},
		{name:"actions", classes: "moon-objaction-actions"}
	],
	//*@protected
	orientationChanged: function () {
		var vertical = this.getOrientation() == "vertical";
		this.addRemoveClass("vertical", vertical);
		this.addRemoveClass("horizontal", !vertical);
		this.$.actions.addRemoveClass("moon-vspacing", vertical);
		this.$.actions.addRemoveClass("moon-hspacing", !vertical);
	},
	noStretchChanged: function() {
		this.$.actions.addRemoveClass("stretch", !this.noStretch);
	},
	initComponents: function() {
		this.inherited(arguments);
		if (this.actionComponents) {
			var owner = this.hasOwnProperty("actionComponents") ? this.getInstanceOwner() : this;
			this.$.actions.createComponents(this.actionComponents, {owner: owner});
		}
		this.orientationChanged();
		this.noStretchChanged();
	},
	spotFocused: function(inSender, inEvent) {
		this.focused = true;
		this.updateActionsVisibility();
	},
	spotBlur: function(inSender, inEvent) {
		this.focused = false;
		this.entered = false;
		this.updateActionsVisibility();
	},
	enter: function(inSender, inEvent) {
		this.entered = true;
		this.updateActionsVisibility();
	},
	leave: function(inSender, inEvent) {
		this.entered = false;
		this.updateActionsVisibility();
	},
	updateActionsVisibility: function() {
		this.$.actions.applyStyle("opacity", (this.focused || this.entered) ? 1 : 0);
	}
});<|endoftext|>


<commit_before>'use strict';

import React from 'react/addons';
import _                from 'lodash';

var Header = React.createClass({
    render() {

        if ( _.isEmpty(localStorage.getItem('key')) ) {
            var login = Login
            var register = Register
        }else{
            var logout = Logout
        }

        return (

                        <button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                            Toggle navigation

                        </button>
                        React and Parse

                        <form className="navbar-form navbar-right">
                            {login}
                            {register}
                            {logout}
                        </form>

        );
    }
});

export default Header;
<commit_msg>logout<commit_after>'use strict';

import React from 'react/addons';
import _                from 'lodash';

var Header = React.createClass({

    onLogout(event){
        event.preventDefault();
        localStorage.removeItem('key');
        localStorage.removeItem('user');
        localStorage.removeItem('email');
        localStorage.removeItem('createdAt');
        localStorage.removeItem('updatedAt');
    },

    render() {

        if ( _.isEmpty(localStorage.getItem('key')) ) {
            var login = Login
            var register = Register
        }else{
            var logout = Logout
        }

        return (

                        <button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                            Toggle navigation

                        </button>
                        React and Parse

                        <form className="navbar-form navbar-right">
                            {login}
                            {register}
                            {logout}
                        </form>

        );
    }
});

export default Header;
<|endoftext|>