<commit_before>/*
This file is part of Archivematica.

Copyright 2010-2012 Artefactual Systems Inc. <http://artefactual.com>

Archivematica is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Archivematica is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Archivematica.  If not, see <http://www.gnu.org/licenses/>.
*/

$(function()
  {
    window.Sip = Sip.extend({
      methodUrl: {
        delete: '/ingest/uuid/delete/'
      }
    });

    window.SipCollection = Backbone.Collection.extend({

      model: Sip,

      url: '/ingest/status/',

      initialize: function()
        {

        },

      comparator: function(sip)
        {
          return -1 * sip.get('timestamp');
        }

    });

    window.SipView = BaseSipView.extend({

      template: _.template($('#sip-template').html()),

      initialize: function()
        {
          _.bindAll(this, 'render', 'update', 'updateIcon');
          this.model.view = this;
          this.model.bind('change:timestamp', this.update);
        },

      openPanel: function(event)
        {
          event.preventDefault();

          window.location = '/ingest/' + this.model.get('uuid') + '/';
        },

      remove: function(event)
        {
          event.preventDefault();
          event.stopPropagation();

          $(this.el).addClass('sip-removing');

          var self = this;

          $('
' +
              '
Are you sure you want to remove this SIP from the dashboard? Note that this does not delete the SIP or related entities.
' +
              '
Directory: ' + this.model.get('directory') + '
UUID: ' + this.model.get('uuid') + '
Status: ' + $(this.el).find('.sip-detail-icon-status > img').attr('title') + '
' +
            '
').dialog(
            {
              modal: true,
              resizable: false,
              draggable: false,
              title: 'Remove SIP',
              width: 480,
              close: function(event, ui)
                {
                  if (event.which !== undefined)
                  {
                    $(self.el).removeClass('sip-removing');
                  }
                },
              buttons: [
                  {
                    text: 'Confirm',
                    click: function() {

                      var $dialog = $(this);

                      self.model.destroy({
                        success: function (model, response)
                          {
                            $dialog.dialog('close');

                            setTimeout(function()
                              {
                                $(self.el).hide('blind', function()
                                  {
                                    $(this).remove();
                                  });
                              }, 250);
                          },
                        error: function(model, response)
                          {
                            $dialog.dialog('close');
                            $(self.el).removeClass('sip-removing');
                          }

                      });
                    }
                  },
                  {
                    text: 'Cancel',
                    click: function() {
                        $(this).dialog('close');
                        $(self.el).removeClass('sip-removing');
                      }
                  }]
            });
        },

       openMetadataEditor: function(event)
        {
          event.stopPropagation();
          event.preventDefault();

          var url = '/ingest/metadata/' + this.model.get('uuid') + '/';
          var self = this;

          var showDialog = function(data)
            {
              var dialog = $('

')
                .append(_.template($('#metadata-dialog').html(), data))
                .dialog({
                  title: 'Dublin Core metadata editor',
                  width: 610,
                  height: 480,
                  modal: true,
                  resizable: false,
                  buttons: [
                    {
                      text: 'Close',
                      click: function()
                        {
                          $(this).dialog('close');
                        }
                    },
                    {
                      text: 'Save',
                      click: function()
                        {
                          $.ajax({
                            context: this,
                            type: 'POST',
                            dataType: 'json',
                            data: $(this).find('form').serialize(),
                            success: function()
                              {
                                $(this).dialog('close');
                              },
                            error: function()
                              {
                                alert("Error.");
                              },
                            url: url});
                        }
                    }]
                });

              if (self.model.jobs.detect(function(job)
                {
                  return job.get('type') === 'Normalize submission documentation to preservation format';
                }))
              {
                dialog.find('input, select, textarea').prop('disabled', true).addClass('disabled');
                dialog.dialog('option', 'buttons', dialog.dialog('option', 'buttons').splice(0,1));
              }
            };

          $.ajax({
            type: 'GET',
            dataType: 'json',
            success: function(data)
              {
                showDialog(data);
              },
            url: url
          });

        }
    });

    window.JobView = BaseJobView.extend({

      className: 'job',

      events: {
        'click .btn_browse_job': 'browseJob',
        'click .btn_approve_job': 'approveJob',
        'click .btn_reject_job': 'rejectJob',
        'click .btn_show_tasks': 'showTasks',
        'click .btn_normalization_report': 'normalizationReport',
        'change select': 'action'
      },

      template: _.template($('#job-template').html()),

      render: function()
        {
          $(this.el).html(this.template(this.model.toJSON()));

          $(this.el).css(
            'background-color',
            this.getStatusColor(this.model.get('currentstep'))
          );

          // Micro-services requiring approval
          if (1 === this.model.get('status'))
          {
            this.$('.job-detail-actions')
              .append('Browse')
              .append('Approve')
              .append('Reject');
          }
          else
          {
            // ...
          }

          choices = this.model.get('choices');

          if (choices)
          {
            var $select = $('<select />').append('<option>Actions</option>')
              , numberOfChoices = Object.keys(choices).length;

            // use pop-up action selector for long choice lists
            if (numberOfChoices >= 10)
            {
              var statusObject = {};
              this.activateEnhancedActionSelect($select, statusObject);
            }

            for (var code in choices)
            {
              $select.append('<option value="' + code + '">- ' + choices[code] + '</option>');
            }

            this.$('.job-detail-actions').append($select);
          }

          if ('Approve normalization' == this.model.get('type'))
          {
            this.$('.job-detail-actions')
              .append('Report');
          }

          this.$('.job-detail-microservice > a').tooltip();

          this.$('.job-detail-actions > a').twipsy();

          return this;
        },

      action: function(event)
        {
          var $select = $(event.target);
          var value = $select.val();

          // Define function to execute
          var executeCommand = function(context)
            {
              $.ajax({
                context: this,
                data: { uuid: context.model.get('uuid'), choice: value },
                type: 'POST',
                success: function(data)
                  {
                    context.model.set({
                      'currentstep': 'Executing command(s)',
                      'status': 0
                    });

                    context.model.sip.view.updateIcon();
                  },
                url: '/mcp/execute/'
              });
            };

          if ('Upload DIP' == this.model.get('type') && 2 == value)
          {
            var modal = $('#upload-dip-modal');
            var input = modal.find('input');
            var process = false;
            var url = '/ingest/' + this.model.sip.get('uuid') + '/upload/';
            var self = this;

            modal

              .one('show', function()
                {
                  var xhr = $.ajax(url, { type: 'GET' });
                  xhr
                    .done(function(data)
                      {
                        if (data.target)
                        {
                          input.filter(':text').val(data.target);
                          input.filter(':checkbox').prop('checked', data.intermediate);
                        }
                      });
                })

              .one('hidden', function()
                {
                  input.filter(':text').val('');
                  input.filter(':checkbox').prop('checked', false);
                  $select.val(0);
                  modal.find('a.primary, a.secondary').unbind('click');
                })

              .find('a.primary').bind('click', function(event)
                {
                  event.preventDefault();

                  if (input.filter(':text').val())
                  {
                    var xhr = $.ajax(url, { type: 'POST', data: {
                      'target': input.filter(':text').val(),
                      'intermediate': input.filter(':checkbox').is(':checked') }})

                      .done(function(data)
                        {
                          if (data.ready)
                          {
                            executeCommand(self);
                          }
                        })
                      .fail(function()
                        {
                          alert("Error.");
                          $select.val(0);
                        })
                      .always(function()
                        {
                          modal.modal('hide');
                        });
                  }
                })
              .end()

              .find('a.secondary').bind('click', function(event)
                {
                  event.preventDefault();
                  $select.val(0);
                  modal.modal('hide');
                })
              .end()

              .modal('show');

            return false;
          }

          executeCommand(this);
        },

      normalizationReport: function(event)
        {
          event.preventDefault();

          $.ajax({
            context: this,
            type: 'GET',
            dataType: 'html',
            success: function(data)
              {
                $('

')
                  .append('
' + $(data).find('thead').html() + $(data).find('tbody').html() + '
')
                  .dialog({
                    title: this.model.sip.get('directory') + ' &raquo ' + this.model.get('type') + ' &raquo Normalization report',
                    width: 860,
                    height: 640,
                    modal: true,
                    buttons: [
                      {
                        text: 'Close',
                        click: function() { $(this).dialog('close'); }
                      }]
                  })
                  .find('a.file-location')
                    .popover(
                      {
                        trigger: 'hover',
                        content: function()
                          {
                            return $(this).attr('data-location').replace(/%.*%/gi, '');
                          }
                      }).click(function(event) { event.preventDefault(); });
              },
            url: '/ingest/normalization-report/' + this.model.sip.get('uuid') + '/'
          });
        }

    });

    window.DirectoryBrowserView = BaseDirectoryBrowserView.extend({
      template: _.template($('#directory-browser-template').html())
    });

    window.AppView = BaseAppView.extend({
      el: $('#sip-container')
    });

    $.fn.tooltip = tooltipPlugin;
    window.onresize = optimizeWidth;
    window.onload = optimizeWidth;

    $(document).ready(function()
      {
        // Create modal
        $('#upload-dip-modal')
          .modal({
            backdrop: true,
            keyboard: true
          });
      });

  }
);
<commit_msg>Got rid of ^M characters.<commit_after>/*
This file is part of Archivematica.

Copyright 2010-2012 Artefactual Systems Inc. <http://artefactual.com>

Archivematica is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Archivematica is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Archivematica.  If not, see <http://www.gnu.org/licenses/>.
*/

$(function()
  {
    window.Sip = Sip.extend({
      methodUrl: {
        delete: '/ingest/uuid/delete/'
      }
    });

    window.SipCollection = Backbone.Collection.extend({

      model: Sip,

      url: '/ingest/status/',

      initialize: function()
        {

        },

      comparator: function(sip)
        {
          return -1 * sip.get('timestamp');
        }

    });

    window.SipView = BaseSipView.extend({

      template: _.template($('#sip-template').html()),

      initialize: function()
        {
          _.bindAll(this, 'render', 'update', 'updateIcon');
          this.model.view = this;
          this.model.bind('change:timestamp', this.update);
        },

      openPanel: function(event)
        {
          event.preventDefault();

          window.location = '/ingest/' + this.model.get('uuid') + '/';
        },

      remove: function(event)
        {
          event.preventDefault();
          event.stopPropagation();

          $(this.el).addClass('sip-removing');

          var self = this;

          $('
' +
              '
Are you sure you want to remove this SIP from the dashboard? Note that this does not delete the SIP or related entities.
' +
              '
Directory: ' + this.model.get('directory') + '
UUID: ' + this.model.get('uuid') + '
Status: ' + $(this.el).find('.sip-detail-icon-status > img').attr('title') + '
' +
            '
').dialog(
            {
              modal: true,
              resizable: false,
              draggable: false,
              title: 'Remove SIP',
              width: 480,
              close: function(event, ui)
                {
                  if (event.which !== undefined)
                  {
                    $(self.el).removeClass('sip-removing');
                  }
                },
              buttons: [
                  {
                    text: 'Confirm',
                    click: function() {

                      var $dialog = $(this);

                      self.model.destroy({
                        success: function (model, response)
                          {
                            $dialog.dialog('close');

                            setTimeout(function()
                              {
                                $(self.el).hide('blind', function()
                                  {
                                    $(this).remove();
                                  });
                              }, 250);
                          },
                        error: function(model, response)
                          {
                            $dialog.dialog('close');
                            $(self.el).removeClass('sip-removing');
                          }

                      });
                    }
                  },
                  {
                    text: 'Cancel',
                    click: function() {
                        $(this).dialog('close');
                        $(self.el).removeClass('sip-removing');
                      }
                  }]
            });
        },

       openMetadataEditor: function(event)
        {
          event.stopPropagation();
          event.preventDefault();

          var url = '/ingest/metadata/' + this.model.get('uuid') + '/';
          var self = this;

          var showDialog = function(data)
            {
              var dialog = $('

')
                .append(_.template($('#metadata-dialog').html(), data))
                .dialog({
                  title: 'Dublin Core metadata editor',
                  width: 610,
                  height: 480,
                  modal: true,
                  resizable: false,
                  buttons: [
                    {
                      text: 'Close',
                      click: function()
                        {
                          $(this).dialog('close');
                        }
                    },
                    {
                      text: 'Save',
                      click: function()
                        {
                          $.ajax({
                            context: this,
                            type: 'POST',
                            dataType: 'json',
                            data: $(this).find('form').serialize(),
                            success: function()
                              {
                                $(this).dialog('close');
                              },
                            error: function()
                              {
                                alert("Error.");
                              },
                            url: url});
                        }
                    }]
                });

              if (self.model.jobs.detect(function(job)
                {
                  return job.get('type') === 'Normalize submission documentation to preservation format';
                }))
              {
                dialog.find('input, select, textarea').prop('disabled', true).addClass('disabled');
                dialog.dialog('option', 'buttons', dialog.dialog('option', 'buttons').splice(0,1));
              }
            };

          $.ajax({
            type: 'GET',
            dataType: 'json',
            success: function(data)
              {
                showDialog(data);
              },
            url: url
          });

        }
    });

    window.JobView = BaseJobView.extend({

      className: 'job',

      events: {
        'click .btn_browse_job': 'browseJob',
        'click .btn_approve_job': 'approveJob',
        'click .btn_reject_job': 'rejectJob',
        'click .btn_show_tasks': 'showTasks',
        'click .btn_normalization_report': 'normalizationReport',
        'change select': 'action'
      },

      template: _.template($('#job-template').html()),

      render: function()
        {
          $(this.el).html(this.template(this.model.toJSON()));

          $(this.el).css(
            'background-color',
            this.getStatusColor(this.model.get('currentstep'))
          );

          // Micro-services requiring approval
          if (1 === this.model.get('status'))
          {
            this.$('.job-detail-actions')
              .append('Browse')
              .append('Approve')
              .append('Reject');
          }
          else
          {
            // ...
          }

          choices = this.model.get('choices');

          if (choices)
          {
            var $select = $('<select />').append('<option>Actions</option>')
              , numberOfChoices = Object.keys(choices).length;

            // use pop-up action selector for long choice lists
            if (numberOfChoices >= 10)
            {
              var statusObject = {};
              this.activateEnhancedActionSelect($select, statusObject);
            }

            for (var code in choices)
            {
              $select.append('<option value="' + code + '">- ' + choices[code] + '</option>');
            }

            this.$('.job-detail-actions').append($select);
          }

          if ('Approve normalization' == this.model.get('type'))
          {
            this.$('.job-detail-actions')
              .append('Report');
          }

          this.$('.job-detail-microservice > a').tooltip();

          this.$('.job-detail-actions > a').twipsy();

          return this;
        },

      action: function(event)
        {
          var $select = $(event.target);
          var value = $select.val();

          // Define function to execute
          var executeCommand = function(context)
            {
              $.ajax({
                context: this,
                data: { uuid: context.model.get('uuid'), choice: value },
                type: 'POST',
                success: function(data)
                  {
                    context.model.set({
                      'currentstep': 'Executing command(s)',
                      'status': 0
                    });

                    context.model.sip.view.updateIcon();
                  },
                url: '/mcp/execute/'
              });
            };

          if ('Upload DIP' == this.model.get('type') && 2 == value)
          {
            var modal = $('#upload-dip-modal');
            var input = modal.find('input');
            var process = false;
            var url = '/ingest/' + this.model.sip.get('uuid') + '/upload/';
            var self = this;

            modal

              .one('show', function()
                {
                  var xhr = $.ajax(url, { type: 'GET' });
                  xhr
                    .done(function(data)
                      {
                        if (data.target)
                        {
                          input.filter(':text').val(data.target);
                          input.filter(':checkbox').prop('checked', data.intermediate);
                        }
                      });
                })

              .one('hidden', function()
                {
                  input.filter(':text').val('');
                  input.filter(':checkbox').prop('checked', false);
                  $select.val(0);
                  modal.find('a.primary, a.secondary').unbind('click');
                })

              .find('a.primary').bind('click', function(event)
                {
                  event.preventDefault();

                  if (input.filter(':text').val())
                  {
                    var xhr = $.ajax(url, { type: 'POST', data: {
                      'target': input.filter(':text').val(),
                      'intermediate': input.filter(':checkbox').is(':checked') }})

                      .done(function(data)
                        {
                          if (data.ready)
                          {
                            executeCommand(self);
                          }
                        })
                      .fail(function()
                        {
                          alert("Error.");
                          $select.val(0);
                        })
                      .always(function()
                        {
                          modal.modal('hide');
                        });
                  }
                })
              .end()

              .find('a.secondary').bind('click', function(event)
                {
                  event.preventDefault();
                  $select.val(0);
                  modal.modal('hide');
                })
              .end()

              .modal('show');

            return false;
          }

          executeCommand(this);
        },

      normalizationReport: function(event)
        {
          event.preventDefault();

          $.ajax({
            context: this,
            type: 'GET',
            dataType: 'html',
            success: function(data)
              {
                $('

')
                  .append('
' + $(data).find('thead').html() + $(data).find('tbody').html() + '
')
                  .dialog({
                    title: this.model.sip.get('directory') + ' &raquo ' + this.model.get('type') + ' &raquo Normalization report',
                    width: 860,
                    height: 640,
                    modal: true,
                    buttons: [
                      {
                        text: 'Close',
                        click: function() { $(this).dialog('close'); }
                      }]
                  })
                  .find('a.file-location')
                    .popover(
                      {
                        trigger: 'hover',
                        content: function()
                          {
                            return $(this).attr('data-location').replace(/%.*%/gi, '');
                          }
                      }).click(function(event) { event.preventDefault(); });
              },
            url: '/ingest/normalization-report/' + this.model.sip.get('uuid') + '/'
          });
        }

    });

    window.DirectoryBrowserView = BaseDirectoryBrowserView.extend({
      template: _.template($('#directory-browser-template').html())
    });

    window.AppView = BaseAppView.extend({
      el: $('#sip-container')
    });

    $.fn.tooltip = tooltipPlugin;
    window.onresize = optimizeWidth;
    window.onload = optimizeWidth;

    $(document).ready(function()
      {
        // Create modal
        $('#upload-dip-modal')
          .modal({
            backdrop: true,
            keyboard: true
          });
      });

  }
);
<|endoftext|>


<commit_before>/*
 * Copyright © 2013 VillageReach.  All Rights Reserved.  This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
 *
 * If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

function RefrigeratorController($scope, $dialog, messageService, refrigerators, distribution, IndexedDB, $routeParams) {

  $scope.refrigerators = refrigerators;
  $scope.distribution = distribution;
  $scope.selectedFacilityId = $routeParams.facility;
  $scope.edit = {};

  $scope.setEdit = function (serialNum) {
    angular.forEach($scope.edit, function (value, key) {
      $scope.edit[key] = false;
    });
    $scope.edit[serialNum] = true;
  };

  $scope.addRefrigeratorToStore = function () {
    var exists = _.find($scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings, function (reading) {
      return reading.refrigerator.serialNumber.toLowerCase() === $scope.newRefrigerator.serialNumber.toLowerCase();
    });
    if (exists) {
      $scope.isDuplicateSerialNumber = true;
      return;
    }
    $scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings.push({'refrigerator': angular.copy($scope.newRefrigerator)});
    IndexedDB.put('distributions', $scope.distribution);
    $scope.addRefrigeratorModal = $scope.isDuplicateSerialNumber = $scope.newRefrigerator = undefined;
  };

  $scope.showDeleteRefrigeratorConfirmationModel = function (serialNum) {
    var dialogOpts = {
      id: "deleteRefrigeratorInfo",
      header: messageService.get('delete.refrigerator.readings.header'),
      body: messageService.get('delete.refrigerator.readings.confirm')
    };
    $scope.serialNum = serialNum;
    OpenLmisDialog.newDialog(dialogOpts, $scope.deleteRefrigeratorReading, $dialog, messageService);
  };

  $scope.deleteRefrigeratorReading = function (result) {
    if (!result) return;
    $scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings.splice(getRefrigeratorIndex(), 1);
    IndexedDB.put('distributions', $scope.distribution);
  };

  function getRefrigeratorIndex() {
    var position = null;
    angular.forEach($scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings, function (refrigeratorReading, index) {
      if ($scope.serialNum != null && $scope.serialNum == refrigeratorReading.refrigerator.serialNumber) {
        position = index;
      }
    });
    return position;
  }

  $scope.deleteOtherProblems = function (refrigeratorReading) {
    if (refrigeratorReading.problemSinceLastTime || !refrigeratorReading.problems) return;

    for (var key in refrigeratorReading.problems.problemMap) {
      refrigeratorReading.problems.problemMap[key] = undefined
    }
    refrigeratorReading.problems.other = undefined;
  };

}

RefrigeratorController.resolve = {
  refrigerators: function ($q, IndexedDB, $route) {
    var waitOn = $q.defer();
    var distributionId = $route.current.params.distribution;
    var facilityId = $route.current.params.facility;

    IndexedDB.get('distributionReferenceData', utils.parseIntWithBaseTen(distributionId), function (event) {
      waitOn.resolve(_.where(event.target.result.refrigerators, {facilityId: utils.parseIntWithBaseTen(facilityId)}));
    }, {});

    return waitOn.promise;
  },

  distribution: function ($q, IndexedDB, $route) {
    var waitOn = $q.defer();
    IndexedDB.get('distributions', utils.parseIntWithBaseTen($route.current.params.distribution), function (e) {
      waitOn.resolve(e.target.result);
    }, {});

    return waitOn.promise;
  }
};

<commit_msg>|#776| +Manan| delete dialog box refactoring<commit_after>/*
 * Copyright © 2013 VillageReach.  All Rights Reserved.  This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
 *
 * If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

function RefrigeratorController($scope, $dialog, messageService, refrigerators, distribution, IndexedDB, $routeParams) {

  $scope.refrigerators = refrigerators;
  $scope.distribution = distribution;
  $scope.selectedFacilityId = $routeParams.facility;
  $scope.edit = {};

  $scope.setEdit = function (serialNum) {
    angular.forEach($scope.edit, function (value, key) {
      $scope.edit[key] = false;
    });
    $scope.edit[serialNum] = true;
  };

  $scope.addRefrigeratorToStore = function () {
    var exists = _.find($scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings,
        function (reading) {
          return reading.refrigerator.serialNumber.toLowerCase() === $scope.newRefrigerator.serialNumber.toLowerCase();
        });
    if (exists) {
      $scope.isDuplicateSerialNumber = true;
      return;
    }
    $scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings.push(
        {'refrigerator': angular.copy($scope.newRefrigerator)});
    IndexedDB.put('distributions', $scope.distribution);
    $scope.addRefrigeratorModal = $scope.isDuplicateSerialNumber = $scope.newRefrigerator = undefined;
  };

  $scope.showDeleteRefrigeratorConfirmationModel = function (serialNumberToDelete) {
    var dialogOpts = {
      id: "deleteRefrigeratorInfo",
      header: messageService.get('delete.refrigerator.readings.header'),
      body: messageService.get('delete.refrigerator.readings.confirm')
    };

    var callback = function (serialNumberToDelete) {
      return function (result) {
        if (!result) return;
        $scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings =
            _.reject($scope.distribution.facilityDistributionData[$scope.selectedFacilityId].refrigeratorReadings,
                function (refrigeratorReading) {
                  return serialNumberToDelete == refrigeratorReading.refrigerator.serialNumber;
                });
        IndexedDB.put('distributions', $scope.distribution);
      };
    };

    OpenLmisDialog.newDialog(dialogOpts, callback(serialNumberToDelete), $dialog, messageService);
  };

  $scope.deleteOtherProblems = function (refrigeratorReading) {
    if (refrigeratorReading.problemSinceLastTime || !refrigeratorReading.problems) return;

    for (var key in refrigeratorReading.problems.problemMap) {
      refrigeratorReading.problems.problemMap[key] = undefined
    }
    refrigeratorReading.problems.other = undefined;
  };

}

RefrigeratorController.resolve = {
  refrigerators: function ($q, IndexedDB, $route) {
    var waitOn = $q.defer();
    var distributionId = $route.current.params.distribution;
    var facilityId = $route.current.params.facility;

    IndexedDB.get('distributionReferenceData', utils.parseIntWithBaseTen(distributionId), function (event) {
      waitOn.resolve(_.where(event.target.result.refrigerators, {facilityId: utils.parseIntWithBaseTen(facilityId)}));
    }, {});

    return waitOn.promise;
  },

  distribution: function ($q, IndexedDB, $route) {
    var waitOn = $q.defer();
    IndexedDB.get('distributions', utils.parseIntWithBaseTen($route.current.params.distribution), function (e) {
      waitOn.resolve(e.target.result);
    }, {});

    return waitOn.promise;
  }
};

<|endoftext|>


<commit_before>/**!
 *
 * Copyright (c) 2015-2017 Cisco Systems, Inc. See LICENSE file.
 */

import '@ciscospark/internal-plugin-presence';

import {assert} from '@ciscospark/test-helper-chai';
import CiscoSpark from '@ciscospark/spark-core';
import testUsers from '@ciscospark/test-helper-test-users';

describe(`plugin-presence`, function() {
  this.timeout(60000);
  describe(`Presence`, () => {
    let mccoy, spock;

    before(`create users`, () => testUsers.create({count: 2})
      .then((users) => {
        [spock, mccoy] = users;
        spock.spark = new CiscoSpark({
          credentials: {
            authorization: users[0].token
          }
        });
        mccoy.spark = new CiscoSpark({
          credentials: {
            authorization: users[1].token
          }
        });
      })
    );

    before(`register with wdm`, () => Promise.all([
      spock.spark.internal.device.register(),
      mccoy.spark.internal.device.register()
    ]));

    describe(`#get()`, () => {
      it(`gets a person's status by id`, () => {
        return spock.spark.internal.presence.get(mccoy.id)
          .then((presenceResponse) => {
            assert.property(presenceResponse, mccoy.id);
          });
      });

      it(`returns an object with the status of all requested people`, () => {
        return spock.spark.internal.presence.get([mccoy.id, spock.id])
          .then((presenceResponse) => {
            assert.isAbove(Object.keys(presenceResponse).length, 0);
            assert.property(presenceResponse, mccoy.id);
            assert.property(presenceResponse, spock.id);
          });
      });
    });

    describe(`#subscribe`, () => {
      it(`subscribes to and returns current status of a person id`, () => spock.spark.internal.presence.subscribe(mccoy.id)
        .then((presenceResponse) => assert.isDefined(presenceResponse[mccoy.id]))
      );

      it(`subscribes and returns current status of a list of people ids`, () =>
        spock.spark.internal.presence.subscribe([mccoy.id, spock.id])
          .then((presenceResponse) => {
            assert.isAbove(Object.keys(presenceResponse).length, 0);
            assert.property(presenceResponse, mccoy.id);
            assert.property(presenceResponse, spock.id);
          })
      );
    });

    describe(`#unsubscribe`, () => {
      it(`unsubscribes to presence updates of a single person id`, () =>
        spock.spark.internal.presence.unsubscribe(mccoy.id)
          .then((res) => assert.statusCode(res, 200))
      );

      it(`unsubscribes to presence updates of a list of people ids`, () =>
        spock.spark.internal.presence.unsubscribe([mccoy.id, spock.id])
          .then((res) => assert.statusCode(res, 200))
      );
    });

    describe(`#setStatus`, () => {
      it(`sets the presence status of the current user`, () =>
        spock.spark.internal.presence.setStatus(`dnd`, 1500)
          .then((statusResponse) => {
            assert.property(statusResponse, spock.id);
            assert.equal(statusResponse[spock.id].status, `dnd`);
          })
      );
    });
  });
});
<commit_msg>test(internal-plugin-presence): add mercury event test<commit_after>/**!
 *
 * Copyright (c) 2015-2017 Cisco Systems, Inc. See LICENSE file.
 */
import '@ciscospark/internal-plugin-mercury';
import '@ciscospark/internal-plugin-presence';

import {assert} from '@ciscospark/test-helper-chai';
import CiscoSpark from '@ciscospark/spark-core';
import testUsers from '@ciscospark/test-helper-test-users';

describe(`plugin-presence`, function() {
  this.timeout(10000);
  describe(`Presence`, () => {
    let mccoy, spock;

    before(`create users`, () => testUsers.create({count: 2})
      .then((users) => {
        [spock, mccoy] = users;
        spock.spark = new CiscoSpark({
          credentials: {
            authorization: users[0].token
          }
        });
        mccoy.spark = new CiscoSpark({
          credentials: {
            authorization: users[1].token
          }
        });
      })
    );

    before(`register with wdm`, () => Promise.all([
      spock.spark.internal.device.register(),
      mccoy.spark.internal.device.register()
    ]));

    before(`register spock with mercury`, () => spock.spark.internal.mercury.connect());

    after(`deregister spock with mercury`, () => spock.spark.internal.mercury.disconnect());

    describe(`#get()`, () => {
      it(`gets a person's status by id`, () => {
        return spock.spark.internal.presence.get(mccoy.id)
          .then((presenceResponse) => {
            assert.property(presenceResponse, mccoy.id);
          });
      });

      it(`returns an object with the status of all requested people`, () => {
        return spock.spark.internal.presence.get([mccoy.id, spock.id])
          .then((presenceResponse) => {
            assert.isAbove(Object.keys(presenceResponse).length, 0);
            assert.property(presenceResponse, mccoy.id);
            assert.property(presenceResponse, spock.id);
          });
      });
    });

    describe(`#subscribe`, () => {
      it(`subscribes to and returns current status of a person id`, () => spock.spark.internal.presence.subscribe(mccoy.id)
        .then((presenceResponse) => assert.isDefined(presenceResponse[mccoy.id]))
      );

      it(`subscribes and returns current status of a list of people ids`, () =>
        spock.spark.internal.presence.subscribe([mccoy.id, spock.id])
          .then((presenceResponse) => {
            assert.isAbove(Object.keys(presenceResponse).length, 0);
            assert.property(presenceResponse, mccoy.id);
            assert.property(presenceResponse, spock.id);
          })
      );
    });

    describe(`#unsubscribe`, () => {
      it(`unsubscribes to presence updates of a single person id`, () =>
        spock.spark.internal.presence.unsubscribe(mccoy.id)
          .then((res) => assert.statusCode(res, 200))
      );

      it(`unsubscribes to presence updates of a list of people ids`, () =>
        spock.spark.internal.presence.unsubscribe([mccoy.id, spock.id])
          .then((res) => assert.statusCode(res, 200))
      );
    });

    describe(`#setStatus`, () => {
      it(`sets the presence status of the current user`, () =>
        spock.spark.internal.presence.setStatus(`dnd`, 1500)
          .then((statusResponse) => {
            assert.property(statusResponse, spock.id);
            assert.equal(statusResponse[spock.id].status, `dnd`);
          })
      );
    });

    it(`should receive a mercury event for a subscribed person's change`, () =>
      Promise.all([
        spock.spark.internal.presence.subscribe(mccoy.id)
          .then(() => mccoy.spark.internal.presence.setStatus(`dnd`, 1500)),
        spock.spark.internal.mercury.when(`event:apheleia.subscription_update`)
          .then(([event]) => {
            assert.equal(event.data.subject, mccoy.id);
            assert.equal(event.data.status, `dnd`);
          })
      ])
    );
  });
});
<|endoftext|>


<commit_before>const chartId = `${prefix}-chart`;
const chartLoginRequired = `${prefix}-chart-login-required`;
const chartClass = `${prefix}-chart-btn`;
const chartClassDisabled = `${prefix}-chart-btn-disabled`;

const charts = [
    { column: 6, label: "Impressions / hour", config: {metric: 'impressions', rate: 'hour', chunk: 'hour', round: true} },
    { column: 7, label: "Clicks / day", config: {metric: 'clicks', rate: 'day', chunk: 'day', round: true} },
    { column: 9, label: "Spend / day", config: {metric: 'spend', rate: 'day', chunk: 'day', round: false} },
    { column: 10, label: "Sales / day", config: {metric: 'salesCount', rate: 'day', chunk: 'day', round: false} },
    { column: 11, label: "ACOS", config: {metric: 'acos', chunk: 'day', round: false} },
];

chrome.runtime.sendMessage({
    action: 'getAllowedCampaigns',
    entityId: getEntityId(),
},
(response) => {
    const allowedCampaigns = response.data || [];
    window.setInterval(() => {
        let tableRows = $('#campaignTable tbody tr');
        addChartButtons(tableRows, allowedCampaigns);
    }, 100);
});

const templateUrl = chrome.runtime.getURL('dashboard/templates.html');
$.ajax(templateUrl, {
    method: 'GET',
    success: (data) => {
        let dashboard = $('#campaignDashboard');
        dashboard.append(data);
    },
});

function addChartButtons(rows, allowedCampaigns) {
    for (let row of rows) {
        for (let chart of charts) {
            let cells = $(row).children();
            let target = cells[chart.column];
            if (!target || $(target).find(`.${chartClass}`).length > 0)
                continue;

            let select = $(cells[0]).find('select')[0];
            let name = cells[1].innerText;
            if (!select)
                continue;

            let selectName = select.name;
            let campaignId = selectName.split('_').pop();
            campaignId = campaignId.substring(0, campaignId.length - 13); // timestamp is appended for some reason

            let btnClasses = chartClass;
            let allowed = allowedCampaigns.includes(campaignId);
            if (!allowed) {
                btnClasses += ` ${chartClassDisabled}`;
            }
            let btn = $(`<a href="#" class="${btnClasses}"><img src="${chartPng}" /></a>`);
            btn.click(function() {
                let newId = chartId+campaignId+chart.config.metric;
                let popup = btn.parent().find('#'+newId);
                if (!popup.length) {
                    if (allowed) {
                        popup = $('#'+chartId).hide().clone();
                        popup.addClass(chartId);
                    }
                    else {
                        popup = $('#'+chartLoginRequired).hide().clone();
                        popup.addClass(chartLoginRequired);
                    }
                    popup.attr('id', newId);

                    // hard-coded element width below b/c popup.width() doesn't
                    // work as required
                    let pos = btn.position();
                    if (pos.left + 420 > $(document).width()) {
                        popup.css({top: pos.top + btn.height() + 6, left: pos.left + btn.width() - 414});
                    }
                    else {
                        popup.css({top: pos.top + btn.height() + 6, left: pos.left});
                    }
                    btn.after(popup);
                }
                popup.slideDown(200, function() {
                    // Clicking anywhere outside the popup dismisses the chart
                    $(document).on('click', function() {
                        if (!$.contains(popup[0], this)) {
                            popup.hide();
                            $(document).off('click');
                        }
                    });
                });

                if (allowed) {
                    getDataHistory(getEntityId(), campaignId, (data) => {
                        renderChart(data, name, Object.assign({id: newId}, chart));
                    });
                }
            });
            $(target).append(btn);
        }
    }
}

function getDataHistory(entityId, campaignId, cb) {
    chrome.runtime.sendMessage({
        action: 'getDataHistory',
        entityId: entityId,
        campaignId: campaignId,
    },
    (response) => cb(response.data));
}

function renderChart(data, name, opt) {
    opt.config.startTimestamp = Date.now() - (8 * span.day);
    data = parallelizeHistoryData(data, opt.config);

    const series = {
      x: data.timestamps,
      y: data[opt.config.metric],
      mode: 'lines+markers',
      name: opt.config.metric,
      connectgaps: true
    };

    let height = 300;
    if (data.timestamps.length < 3) {
        height = 270; // leaving room for the lodata link
    }

    const layout = {
      title: `${opt.label}<br />${name}`,
      width: 400,
      height,
      margin: { l: 40, r: 20, b: 25, t: 60, pad: 4 },
    };

    Plotly.newPlot(opt.id, [series], layout, {displayModeBar: false});

    let container = $('#'+opt.id);
    if (data.timestamps.length < 3) {
        let a = container.find(`a.${prefix}-lodata`);
        a[0].href = chrome.runtime.getURL('common/low-data.html');
        a.show();
    }
}
<commit_msg>position correctly in case of scrolling, etc.<commit_after>const chartId = `${prefix}-chart`;
const chartLoginRequired = `${prefix}-chart-login-required`;
const chartClass = `${prefix}-chart-btn`;
const chartClassDisabled = `${prefix}-chart-btn-disabled`;

const charts = [
    { column: 6, label: "Impressions / hour", config: {metric: 'impressions', rate: 'hour', chunk: 'hour', round: true} },
    { column: 7, label: "Clicks / day", config: {metric: 'clicks', rate: 'day', chunk: 'day', round: true} },
    { column: 9, label: "Spend / day", config: {metric: 'spend', rate: 'day', chunk: 'day', round: false} },
    { column: 10, label: "Sales / day", config: {metric: 'salesCount', rate: 'day', chunk: 'day', round: false} },
    { column: 11, label: "ACOS", config: {metric: 'acos', chunk: 'day', round: false} },
];

chrome.runtime.sendMessage({
    action: 'getAllowedCampaigns',
    entityId: getEntityId(),
},
(response) => {
    const allowedCampaigns = response.data || [];
    window.setInterval(() => {
        let tableRows = $('#campaignTable tbody tr');
        addChartButtons(tableRows, allowedCampaigns);
    }, 100);
});

const templateUrl = chrome.runtime.getURL('dashboard/templates.html');
$.ajax(templateUrl, {
    method: 'GET',
    success: (data) => {
        let dashboard = $('#campaignDashboard');
        dashboard.append(data);
    },
});

function addChartButtons(rows, allowedCampaigns) {
    for (let row of rows) {
        for (let chart of charts) {
            let cells = $(row).children();
            let target = cells[chart.column];
            if (!target || $(target).find(`.${chartClass}`).length > 0)
                continue;

            let select = $(cells[0]).find('select')[0];
            let name = cells[1].innerText;
            if (!select)
                continue;

            let selectName = select.name;
            let campaignId = selectName.split('_').pop();
            campaignId = campaignId.substring(0, campaignId.length - 13); // timestamp is appended for some reason

            let btnClasses = chartClass;
            let allowed = allowedCampaigns.includes(campaignId);
            if (!allowed) {
                btnClasses += ` ${chartClassDisabled}`;
            }
            let btn = $(`<a href="#" class="${btnClasses}"><img src="${chartPng}" /></a>`);
            btn.click(function() {
                let newId = chartId+campaignId+chart.config.metric;
                let popup = $('#'+newId);
                if (!popup.length) {
                    if (allowed) {
                        popup = $('#'+chartId).hide().clone();
                        popup.addClass(chartId);
                    }
                    else {
                        popup = $('#'+chartLoginRequired).hide().clone();
                        popup.addClass(chartLoginRequired);
                    }
                    popup.attr('id', newId);
                    $(document.body).append(popup);
                }
                // hard-coded element width below b/c popup.width() doesn't
                // work as required. must reposition every time we display in
                // order to work correctly with scrolling.
                let pos = btn.offset();
                if (pos.left + 420 > $(document).width()) {
                    popup.css({top: pos.top + btn.height() + 6, left: pos.left + btn.width() - 414});
                }
                else {
                    popup.css({top: pos.top + btn.height() + 6, left: pos.left});
                }

                popup.slideDown(200, function() {
                    // Clicking anywhere outside the popup dismisses the chart
                    $(document).on('click', function() {
                        if (!$.contains(popup[0], this)) {
                            popup.hide();
                            $(document).off('click');
                        }
                    });
                });

                if (allowed) {
                    getDataHistory(getEntityId(), campaignId, (data) => {
                        renderChart(data, name, Object.assign({id: newId}, chart));
                    });
                }
            });
            $(target).append(btn);
        }
    }
}

function getDataHistory(entityId, campaignId, cb) {
    chrome.runtime.sendMessage({
        action: 'getDataHistory',
        entityId: entityId,
        campaignId: campaignId,
    },
    (response) => cb(response.data));
}

function renderChart(data, name, opt) {
    opt.config.startTimestamp = Date.now() - (8 * span.day);
    data = parallelizeHistoryData(data, opt.config);

    const series = {
      x: data.timestamps,
      y: data[opt.config.metric],
      mode: 'lines+markers',
      name: opt.config.metric,
      connectgaps: true
    };

    let height = 300;
    if (data.timestamps.length < 3) {
        height = 270; // leaving room for the lodata link
    }

    const layout = {
      title: `${opt.label}<br />${name}`,
      width: 400,
      height,
      margin: { l: 40, r: 20, b: 25, t: 60, pad: 4 },
    };

    Plotly.newPlot(opt.id, [series], layout, {displayModeBar: false});

    let container = $('#'+opt.id);
    if (data.timestamps.length < 3) {
        let a = container.find(`a.${prefix}-lodata`);
        a[0].href = chrome.runtime.getURL('common/low-data.html');
        a.show();
    }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('cloudoptingApp')
    .controller('ChooseAccountController', function (SERVICE, Principal, $rootScope, $scope, $state, $timeout, localStorageService, OrganizationService, InstanceService) {

        var instance = localStorageService.get(SERVICE.STORAGE.CURRENT_INSTANCE);

        //Get accounts for organization and show it.
        OrganizationService.findById(instance.customerOrganizationId.id)
            .success(function (organization) {
                $scope.org = organization;
                $scope.cloudAccountsList = organization.cloudAccountss;
            });

        //Selected organization, execute the function with the account selected.
        $scope.choose = function(cloudAccount) {
            var callback = function(data, status, headers, config) {
                checkStatusCallback(data, status, headers, config);
                $state.go('dashboard');
            };
            var instanceWithAccount = {};
            instanceWithAccount.id = instance.id;
            instanceWithAccount.cloudAccountId = cloudAccount.id;
            InstanceService(instanceWithAccount, callback);
        };

        //Error handling
        $scope.errorMessage = null;

        //function to check possible outputs for the end user information.
        var checkStatusCallback = function(data, status, headers, config){
            if(status==401) {
                //Unauthorised. Check if signed in.
                if(Principal.isAuthenticated()){
                    $scope.errorMessage = "You have no permissions to do so. Ask for more permissions to the administrator";
                } else {
                    $scope.errorMessage = "Your session has ended. Sign in again. Redirecting to login...";
                    $timeout(function() {
                        $state.go('login');
                    }, 3000);
                }
            }else if(status!=200 && status!=201) {
                //Show message
                $scope.errorMessage = "An error occurred. Wait a moment and try again, if problem persists contact the administrator";
            } else {
                $log.info("Service customization succeeded with data: " + data);
            }
        };
    }
);<commit_msg>Fix #163<commit_after>'use strict';

angular.module('cloudoptingApp')
    .controller('ChooseAccountController', function (SERVICE, Principal, $rootScope, $scope, $state, $timeout, localStorageService, OrganizationService, InstanceService) {

        var instance = localStorageService.get(SERVICE.STORAGE.CURRENT_INSTANCE);

        //Get accounts for organization and show it.
        OrganizationService.findById(instance.customerOrganizationId.id)
            .success(function (organization) {
                $scope.org = organization;
                $scope.cloudAccountsList = organization.cloudAccountss;
            });

        //Selected organization, execute the function with the account selected.
        $scope.choose = function(cloudAccount) {
            var callback = function(data, status, headers, config) {
                checkStatusCallback(data, status, headers, config);
                $state.go('dashboard');
            };
            var instanceWithAccount = {};
            instanceWithAccount.id = instance.id;
            instanceWithAccount.cloudAccountId = cloudAccount.id;
            InstanceService.update(instanceWithAccount, callback);
        };

        //Error handling
        $scope.errorMessage = null;

        //function to check possible outputs for the end user information.
        var checkStatusCallback = function(data, status, headers, config){
            if(status==401) {
                //Unauthorised. Check if signed in.
                if(Principal.isAuthenticated()){
                    $scope.errorMessage = "You have no permissions to do so. Ask for more permissions to the administrator";
                } else {
                    $scope.errorMessage = "Your session has ended. Sign in again. Redirecting to login...";
                    $timeout(function() {
                        $state.go('login');
                    }, 3000);
                }
            }else if(status!=200 && status!=201) {
                //Show message
                $scope.errorMessage = "An error occurred. Wait a moment and try again, if problem persists contact the administrator";
            } else {
                $log.info("Service customization succeeded with data: " + data);
            }
        };
    }
);<|endoftext|>


<commit_before>"use strict"
const colors = require('colors');
const walk = require('walk');
const fs = require("fs");
const ytdl = require('ytdl-core');

class MusicManager{
  constructor(options){
    this.options = options;
    this.disnode = options.disnode;

    this.following = [];

    this.defaultConfig = {
      commands:[
        {
		      "cmd": "skip",
		      "context": "MusicManager",
		      "run": "cmdSkip",
		      "desc": "Displays list of Audio Files.",
		      "usage": "list [page]",
		    },
				{
		      "cmd": "stream",
		      "context": "MusicManager",
		      "run": "cmdStream",
		      "desc": "Plays an audio file.",
		      "usage": "play [url] [volume]",
		    },
        {
		      "cmd": "clearqueue",
		      "context": "MusicManager",
		      "run": "cmdClearQueue",
		      "desc": "Stopps and Clears all URLS's in Queue",
		      "usage": "clearqueue",
		    },
		    {
		      "cmd": "resume",
		      "context": "MusicManager",
		      "run": "cmdResume",
		      "desc": "Resumes Connection",
		      "usage": "resume",
		    },
        {
		      "cmd": "pause",
		      "context": "MusicManager",
		      "run": "cmdPause",
		      "desc": "Pauses Connection",
		      "usage": "resume",
		    },
				{
          "cmd": "jv",
          "context": "MusicManager",
          "run": "cmdJoinVoice",
          "desc": "Joins the voice channel you are connected to.",
          "usage": "jv"
        },
        {
          "cmd": "lv",
          "context": "MusicManager",
          "run": "cmdLeaveVoice",
          "desc": "Leaves the voice channel you are connected to.",
          "usage": "lv",
        },
        {
          "cmd": "follow",
          "context": "MusicManager",
          "run": "cmdFollowUser",
          "desc": "Test Command that lists all params.",
          "usage": "follow [User]",
        },
        {
          "cmd": "unfollow",
          "context": "MusicManager",
          "run": "cmdUnFollowUser",
          "desc": "Test Command that lists all params.",
          "usage": "unfollow [parms]",
        }
			],
			songs: [],
      maxVolume: 3,
      defaultVolume: 0.8,
			resNoName : "```Please Enter a name for this song!```",
			resNoUrl : "```Please Enter a Youtube URL for this song!```",
			resSongAdded : "```[Song] Added!```",
      resFollow : "**Following: ** [Sender]",
      resUnFollow : "**Stop Following: ** [Sender]",
      resJoiningServer: "**Joining Server: ** [Server]",
      resNotInServer: "**Can't Join You! Try Joining a Channel First!**",
      resMaxVolume: "**Max Volume([MaxVolume]) Reached! Playing at: [DefaultVolume].**",
      resResume: "**Resuming the queue!**",
      resAddedToQueue: "**Added to the queue!**",
      resPause: "**Pausing the queue!**",
      resClearQueue: "**Clearing the queue!**"
    };

    this.config = this.disnode.config.MusicManager || this.defaultConfig;

    if(options.voiceEvents == true){
       options.disnode.bot.on("voiceJoin", (c,u)=>this.OnVoiceJoin(c,u));
       options.disnode.bot.on("voiceLeave", (c,u)=>this.OnVoiceLeave(c,u));
    }
  }

  OnVoiceJoin(channel,user){
    if(this.following.includes(user.username)){
        this.JoinServer(channel);
    }
  }

  OnVoiceLeave(channel,user){
    if(this.following.includes(user.username)){
      this.LeaveServer(channel);
    }
  }

  playStream(connection, vol){
    var self = this;
    connection.playRunning = true;
    connection.setVolume(vol);
    connection.ytStream = ytdl(connection.queue[0], {audioonly: true});
    connection.ytStream.on('end', function(){
      if(connection.queue.length == 0){
        connection.playRunning = false;

      }else{
        connection.queue.splice(0,1);
        self.playStream(connection);
        //connection.ytStream.destory();
      }
    });
		connection.playRawStream(connection.ytStream);
  }
  addUrl(url,connection, vol){
    var bot = this.disnode.bot;

    if(!connection.queue){connection.queue = [];}
    connection.queue.push(url);
    if(!connection.playRunning){
      this.playStream(connection,vol);
    }
  }

  JoinServer(channel){
    var self = this;
    this.disnode.bot.joinVoiceChannel(channel, function(err, connnection){
      if(err){
        console.log(err);
        return;
      }
    });
  }

  LeaveServer(channel){
    var self = this;
    this.disnode.bot.leaveVoiceChannel(channel, function(err, connnection){
      if(err){
        console.log(err);
        return;
      }
    });
  }

  cmdPause(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.pause();
      this.disnode.sendResponse(parsedMsg, this.config.resPause);
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer);
    }
  }

  cmdResume(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.resume();
      this.disnode.sendResponse(parsedMsg, this.config.resResume,{parse: true});
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer,{parse: true});
    }
  }

  cmdStream(parsedMsg){
    var self = this;
    var url = parsedMsg.params[0];
    var vol = this.config.defaultConfig || .8;
    if(parsedMsg.params[1]){
      if(parseFloat(parsedMsg.params[1]) != 'NaN'){
        vol = parseFloat(parsedMsg.params[1]);
      }
    }
    GetVolume(vol, this.config, function(err, res){
      if(!err){
        vol = res;

      }
      if(err == "MAX"){
        var shortcuts = [
          {shortcut: "[DefaultVolume]", data: self.config.defaultVolume},
          {shortcut: "[MaxVolume]", data: self.config.maxVolume},
          {shortcut: "[RequestedVolume]", data: vol}];
        self.disnode.sendResponse(parsedMsg, self.config.resMaxVolume, {parse: true, shortcuts: shortcuts})
      }
    });
    var channel = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(channel){
      this.addUrl(url,channel,vol);
      this.disnode.sendResponse(parsedMsg, self.config.resAddedToQueue);
    }
    else{
      this.disnode.sendResponse(parsedMsg, "Not In Server!");
    }
  }

  cmdJoinVoice(parsedMsg){
    var self = this;
    var channel = parsedMsg.msg.author.voiceChannel;
    var shortcuts = [{
      shortcut: "[Server]",
      data: channel.name
    }];
    if(channel){
      this.JoinServer(channel);
      this.disnode.sendResponse(parsedMsg, this.config.resJoiningServer,{parse: true, shortcuts: shortcuts});
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer,{parse: true});
    }
  }

  cmdLeaveVoice(parsedMsg){
    var channel = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections).voiceChannel;
    this.LeaveServer(channel);
  }

  cmdSkip(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.queue.splice(0,1);
      this.playStream();
    }
  }

  cmdFollowUser(parsedMsg){
    var self = this;
    this.following.push(parsedMsg.msg.author.username);
    console.log(this.following);
    this.disnode.sendResponse(parsedMsg, this.config.resFollow,{parse: true});
  }

  cmdUnFollowUser(parsedMsg){
    var index = this.following.indexOf(parsedMsg.msg.author.username);

    this.following.splice(index,1);

    this.disnode.sendResponse(parsedMsg, this.config.resUnFollow,{parse: true});
  }

  cmdClearQueue(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.queue = [];
      connection.stopPlaying();
      this.disnode.sendResponse(parsedMsg, this.config.resClearQueue);
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer);
    }
  }

}

function GetVoiceConnectionViaMsg(msg, voiceConnections){
  var connection;

  var serverChannels = msg.server.channels;

  for (var i = 0; i < voiceConnections.length; i++) {
    var channel = voiceConnections[i].voiceChannel;

    if(serverChannels.includes(channel)){
      connection = voiceConnections[i];
    }
  }

  return connection;
}

function GetVolume(requestedVol, config, cb){
  var defaultVol = config.defaultVolume || 0.8;
  var maxVol = config.maxVolume || 1;

  if(requestedVol <= maxVol){

    cb(null,requestedVol) ;
  }else{
    cb("MAX", defaultVol);
  }
}

module.exports = MusicManager;
<commit_msg>response<commit_after>"use strict"
const colors = require('colors');
const walk = require('walk');
const fs = require("fs");
const ytdl = require('ytdl-core');

class MusicManager{
  constructor(options){
    this.options = options;
    this.disnode = options.disnode;

    this.following = [];

    this.defaultConfig = {
      commands:[
        {
		      "cmd": "skip",
		      "context": "MusicManager",
		      "run": "cmdSkip",
		      "desc": "Displays list of Audio Files.",
		      "usage": "list [page]",
		    },
				{
		      "cmd": "stream",
		      "context": "MusicManager",
		      "run": "cmdStream",
		      "desc": "Plays an audio file.",
		      "usage": "play [url] [volume]",
		    },
        {
		      "cmd": "clearqueue",
		      "context": "MusicManager",
		      "run": "cmdClearQueue",
		      "desc": "Stopps and Clears all URLS's in Queue",
		      "usage": "clearqueue",
		    },
		    {
		      "cmd": "resume",
		      "context": "MusicManager",
		      "run": "cmdResume",
		      "desc": "Resumes Connection",
		      "usage": "resume",
		    },
        {
		      "cmd": "pause",
		      "context": "MusicManager",
		      "run": "cmdPause",
		      "desc": "Pauses Connection",
		      "usage": "resume",
		    },
				{
          "cmd": "jv",
          "context": "MusicManager",
          "run": "cmdJoinVoice",
          "desc": "Joins the voice channel you are connected to.",
          "usage": "jv"
        },
        {
          "cmd": "lv",
          "context": "MusicManager",
          "run": "cmdLeaveVoice",
          "desc": "Leaves the voice channel you are connected to.",
          "usage": "lv",
        },
        {
          "cmd": "follow",
          "context": "MusicManager",
          "run": "cmdFollowUser",
          "desc": "Test Command that lists all params.",
          "usage": "follow [User]",
        },
        {
          "cmd": "unfollow",
          "context": "MusicManager",
          "run": "cmdUnFollowUser",
          "desc": "Test Command that lists all params.",
          "usage": "unfollow [parms]",
        }
			],
			songs: [],
      maxVolume: 3,
      defaultVolume: 0.8,
			resNoName : "```Please Enter a name for this song!```",
			resNoUrl : "```Please Enter a Youtube URL for this song!```",
			resSongAdded : "```[Song] Added!```",
      resFollow : "**Following: ** [Sender]",
      resUnFollow : "**Stop Following: ** [Sender]",
      resJoiningServer: "**Joining Server: ** [Server]",
      resNotInServer: "**Can't Join You! Try Joining a Channel First!**",
      resMaxVolume: "**Max Volume([MaxVolume]) Reached! Playing at: [DefaultVolume].**",
      resResume: "**Resuming the queue!**",
      resAddedToQueue: "**Added to the queue!**",
      resPause: "**Pausing the queue!**",
      resClearQueue: "**Clearing the queue!**"
    };

    this.config = this.disnode.config.MusicManager || this.defaultConfig;

    if(options.voiceEvents == true){
       options.disnode.bot.on("voiceJoin", (c,u)=>this.OnVoiceJoin(c,u));
       options.disnode.bot.on("voiceLeave", (c,u)=>this.OnVoiceLeave(c,u));
    }
  }

  OnVoiceJoin(channel,user){
    if(this.following.includes(user.username)){
        this.JoinServer(channel);
    }
  }

  OnVoiceLeave(channel,user){
    if(this.following.includes(user.username)){
      this.LeaveServer(channel);
    }
  }

  playStream(connection, vol){
    var self = this;
    connection.playRunning = true;
    connection.setVolume(vol);
    connection.ytStream = ytdl(connection.queue[0], {audioonly: true});
    connection.ytStream.on('end', function(){
      if(connection.queue.length == 0){
        connection.playRunning = false;

      }else{
        connection.queue.splice(0,1);
        self.playStream(connection);
        //connection.ytStream.destory();
      }
    });
		connection.playRawStream(connection.ytStream);
  }
  addUrl(url,connection, vol){
    var bot = this.disnode.bot;

    if(!connection.queue){connection.queue = [];}
    connection.queue.push(url);
    if(!connection.playRunning){
      this.playStream(connection,vol);
    }
  }

  JoinServer(channel){
    var self = this;
    this.disnode.bot.joinVoiceChannel(channel, function(err, connnection){
      if(err){
        console.log(err);
        return;
      }
    });
  }

  LeaveServer(channel){
    var self = this;
    this.disnode.bot.leaveVoiceChannel(channel, function(err, connnection){
      if(err){
        console.log(err);
        return;
      }
    });
  }

  cmdPause(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.pause();
      this.disnode.sendResponse(parsedMsg, this.config.resPause);
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer);
    }
  }

  cmdResume(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.resume();
      this.disnode.sendResponse(parsedMsg, this.config.resResume,{parse: true});
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer,{parse: true});
    }
  }

  cmdStream(parsedMsg){
    var self = this;
    var url = parsedMsg.params[0];
    var vol = this.config.defaultConfig || .8;
    if(parsedMsg.params[1]){
      if(parseFloat(parsedMsg.params[1]) != 'NaN'){
        vol = parseFloat(parsedMsg.params[1]);
      }
    }
    GetVolume(vol, this.config, function(err, res){
      if(!err){
        vol = res;

      }
      if(err == "MAX"){
        var shortcuts = [
          {shortcut: "[DefaultVolume]", data: self.config.defaultVolume},
          {shortcut: "[MaxVolume]", data: self.config.maxVolume},
          {shortcut: "[RequestedVolume]", data: vol}
        ];
        self.disnode.sendResponse(parsedMsg, self.config.resMaxVolume, {parse: true, shortcuts: shortcuts})
      }
    });
    var channel = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(channel){
      var shortcutsAdd = [
        {shortcut: "[url]", data: url},
        {shortcut: "[channel]", data: channel},
        {shortcut: "[vol]", data: vol},
      ];
      this.addUrl(url,channel,vol);
      this.disnode.sendResponse(parsedMsg, self.config.resAddedToQueue, {parse: true, shortcuts: shortcutsAdd});
    }
    else{
      this.disnode.sendResponse(parsedMsg, "Not In Server!");
    }
  }

  cmdJoinVoice(parsedMsg){
    var self = this;
    var channel = parsedMsg.msg.author.voiceChannel;
    var shortcuts = [{
      shortcut: "[Server]",
      data: channel.name
    }];
    if(channel){
      this.JoinServer(channel);
      this.disnode.sendResponse(parsedMsg, this.config.resJoiningServer,{parse: true, shortcuts: shortcuts});
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer,{parse: true});
    }
  }

  cmdLeaveVoice(parsedMsg){
    var channel = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections).voiceChannel;
    this.LeaveServer(channel);
  }

  cmdSkip(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.queue.splice(0,1);
      this.playStream();
    }
  }

  cmdFollowUser(parsedMsg){
    var self = this;
    this.following.push(parsedMsg.msg.author.username);
    console.log(this.following);
    this.disnode.sendResponse(parsedMsg, this.config.resFollow,{parse: true});
  }

  cmdUnFollowUser(parsedMsg){
    var index = this.following.indexOf(parsedMsg.msg.author.username);

    this.following.splice(index,1);

    this.disnode.sendResponse(parsedMsg, this.config.resUnFollow,{parse: true});
  }

  cmdClearQueue(parsedMsg){
    var connection = GetVoiceConnectionViaMsg(parsedMsg.msg, this.disnode.bot.voiceConnections);

    if(connection){
      connection.queue = [];
      connection.stopPlaying();
      this.disnode.sendResponse(parsedMsg, this.config.resClearQueue);
    }else{
      this.disnode.sendResponse(parsedMsg, this.config.resNotInServer);
    }
  }

}

function GetVoiceConnectionViaMsg(msg, voiceConnections){
  var connection;

  var serverChannels = msg.server.channels;

  for (var i = 0; i < voiceConnections.length; i++) {
    var channel = voiceConnections[i].voiceChannel;

    if(serverChannels.includes(channel)){
      connection = voiceConnections[i];
    }
  }

  return connection;
}

function GetVolume(requestedVol, config, cb){
  var defaultVol = config.defaultVolume || 0.8;
  var maxVol = config.maxVolume || 1;

  if(requestedVol <= maxVol){

    cb(null,requestedVol) ;
  }else{
    cb("MAX", defaultVol);
  }
}

module.exports = MusicManager;
<|endoftext|>


<commit_before>/**
 * SettingsView: for settings dialog.
 **/
var $ = require('jquery');
require('jquery-ui');
var Radio = require('backbone.radio');
var Marionette = require('kabuki/src/marionette-shim');
var _ = require('underscore');

var SettingsView = Marionette.ItemView.extend({
    className: 'kb-settings',
    template: _.template('SETTINGS' +
        '

'
    ),

    ui: {
        textSpeed: '.text-speed'
    },

    initialize: function(opts) {
        this.channel = opts.channel;
    },

    onRender: function() {
        $(this.ui.textSpeed).slider({
            value: 50,
            min: 0,
            max: 100,
            step: 20
        });
    }
});

module.exports = SettingsView;
<commit_msg>basic saving of text speed to settings model<commit_after>/**
 * SettingsView: for settings dialog.
 **/
var $ = require('jquery');
require('jquery-ui');
var Radio = require('backbone.radio');
var Marionette = require('kabuki/src/marionette-shim');
var Backbone = require('backbone');
var _ = require('underscore');

var SettingsView = Marionette.ItemView.extend({
    className: 'kb-settings',
    template: _.template('SETTINGS' +
        '

'
    ),

    ui: {
        textSpeed: '.text-speed'
    },

    constructor: function(opts) {
        var decoratedOpts = Object.assign({model: new Backbone.Model()}, opts);
        Marionette.ItemView.prototype.constructor.call(this, decoratedOpts);
    },

    initialize: function(opts) {
        this.channel = opts.channel;
    },

    onRender: function() {
        $(this.ui.textSpeed).slider({
            value: 50,
            min: 0,
            max: 100,
            step: 20,
            change: (e, ui) => {
                this.model.set('textSpeed', ui.value);
            }
        });
    }
});

module.exports = SettingsView;
<|endoftext|>


<commit_before>
// requires assertions

if( JSHC.Test === undefined ) JSHC.Test = {};
if( JSHC.Test.Cases === undefined) JSHC.Test.Cases = {};
////////////////////////////////////////////////////////////////////////////////

/*
  can be created with:
  (name, action)
  (name, action, obj) where 'obj' contains extra properties to copy
  (obj) where 'obj' contains properties to copy (including name and action)
*/
JSHC.Test.TestCase = function(p1, p2, p3){
    var k;

    if( typeof p1 === "string" && p2 instanceof Function ){
	this.name = p1;
	this.action = p2;
	for(k in p3){
	    if( k === "name" || k === "action" ){
		throw new Error("invalid parameters");
	    }
	    this[k] = p1[k];
	}
    } else if( p1 !== undefined &&
	       typeof p1.name === "string" &&
	       p1.action instanceof Function ) {
	for(k in p1){
	    this[k] = p1[k];
	}
    } else {
	throw new Error("invalid parameters");
    }
};

JSHC.Test.TestCase.prototype.result = function(ok, info){
    assert.ok( typeof ok === "boolean" && arguments.length <= 2 );
    return new JSHC.Test.TestResult(this, ok, info);
};

////////////////////////////////////////////////////////////////////////////////

JSHC.Test.TestResult = function(id, ok, info){
    assert.ok( typeof ok == "boolean" );
    if( typeof id == "string" ){
        this.name = id;
    } else if( id instanceof JSHC.Test.TestCase ){
        this.tc = id;
    }
    this.ok = ok;
    if( info !== undefined ){
        assert.ok( typeof info == "string", "test result \""+this.getName()+"\" has a non-string as info");
	this.info = info;
    }
};

JSHC.Test.TestResult.prototype.getName = function(){
    return this.name !== undefined ? this.name : this.tc.name;
};

////////////////////////////////////////////////////////////////////////////////

JSHC.Test.Tester = function(){
    this.results = {};
    this.passed = 0;
    this.failed = 0;
    this.interpreter = new JSHC.Interpreter("JSHC.Test.modules");
};

/*
  Makes a depth-first traversal over the test cases, and runs them.
*/
JSHC.Test.Tester.prototype.run = function(tests){
    var t;

    // run the single test case
    if( tests instanceof JSHC.Test.TestCase ){
	this.runTC(tests);
    } else if( tests instanceof Function ){
        this.runFunction(tests);
    } else {
        // run all test cases in the object
        for(t in tests){
	    this.run(tests[t]);
        }
    }
};

JSHC.Test.Tester.prototype.addResult = function(result){
    assert.ok( result instanceof JSHC.Test.TestResult );
    var name = result.getName();
    if( this.results[name] !== undefined ){
        throw new Error("test names overlap. \""+name+"\" exists more than once.");
    }
    this.results[name] = result;
    if( result.ok ){
        this.passed++;
    } else {
        this.failed++;
    }
};

/*
  Runs a single test case.
*/
JSHC.Test.Tester.prototype.runFunction = function(fun){
    assert.ok( fun instanceof Function );

    //tester = this;
    //var resultHandler = function(result){
    //    tester.addResult(result);
    //};

    fun(this);
};

/*
  Runs a single test case.
*/
JSHC.Test.Tester.prototype.runTC = function(tc){
    assert.ok( tc instanceof JSHC.Test.TestCase );
    this.addResult(tc.action());
};

/*
  Shows test results.
*/
JSHC.Test.Tester.prototype.toString = function(tc){
    var rn,msg = [];
    msg.push("tests passed:" + this.passed + "\n");
    msg.push("tests failed:" + this.failed + "\n");
    msg.push("\n");
    for(rn in this.results){
	var r = this.results[rn];
	assert.ok( r instanceof JSHC.Test.TestResult );

	// ignore passed tests
	if( r.ok )continue;

	// show failed tests
	msg.push("name: "+r.name+"\n");
	if( r.info === undefined || r.info.length == 0 ){
	    msg.push("(no information)");
	} else {
            msg.push(r.info);
	}
	msg.push("\n\n");
    }
    return msg.join("");
};

/*
  Shows test results.
*/
JSHC.Test.Tester.prototype.toHTML = function(tc){
    var rn,msg = [];
    msg.push("
tests passed:" + this.passed + "
");
    msg.push("tests failed:" + this.failed + "
");
    msg.push("

");
    for(rn in this.results){
	var r = this.results[rn];
	assert.ok( r instanceof JSHC.Test.TestResult );

	// ignore passed tests
	if( r.ok )continue;

	// show failed tests
	msg.push("name: "+r.getName()+"
");
	if( r.info === undefined || r.info.length == 0 ){
	    msg.push("(no information)");
	} else {
            // TODO: should somehow convert to HTML ?
            msg.push(r.info.replace(/\n/g,"
"));
	}
	msg.push("
");
    }
    return msg.join("");
};

////////////////////////////////////////////////////////////////////////////////

/*
  Runs the given tests and returns a string describing the results.
*/
JSHC.Test.runtests = function(tests, showHTML){
    var tester = new JSHC.Test.Tester();
    tester.run(tests);
    return showHTML ? tester.toHTML() : tester.toString();
};

////////////////////////////////////////////////////////////////////////////////

/*
  run test tests using test data
*/
JSHC.Test.runData = function(tester,td){
    assert.ok( td.fileSystem !== undefined );

    // set file system
    tester.interpreter.compiler.setFileSystem(td.fileSystem);

    // set targets
    if( td.targets === undefined ){
       var targets = [];
       for(var modname in td.fileSystem){
          targets.push(modname);
       }
    } else {
       targets = td.targets;
    }
    tester.interpreter.compiler.setTargets(targets);

    // compile
    tester.interpreter.compiler.recompile();

    var errorAmount;
    if( td.errors === undefined ){
        errorAmount = 0;
    } else {
        errorAmount = td.errors;
    }

    var info = [];
    if( tester.interpreter.errors !== errorAmount ){
        for(var i=0 ; i<tester.interpreter.errorList.length ; i++){
            var err = tester.interpreter.errorList[i];
            if( typeof err !== "string" ){
                err = JSHC.showError(err);
            }
            info.push(err);
        }
    }

    var success = tester.interpreter.errors === errorAmount;

    var commands = td.commands;
    for(var command in commands){
        tester.interpreter.execCommand(command);
        if ( tester.interpreter.messageList.length === 0 ) {
            success = false;
            info.push("got no result when executing\""+command+"\"");
            info.push(tester.interpreter.messageList.join("\n"))
            continue;
        }
        if( tester.interpreter.messageList.length !== 1 ){
            success = false;
            info.push("got more than one result when executing \""+command+"\":");
            info.push(tester.interpreter.messageList.join("\n"));
            continue;
        }
        if( tester.interpreter.messageList[0] !== commands[command] ){
            success = false;
            info.push("got result \""+tester.interpreter.messageList[0]+"\""+
                      " instead of \""+commands[command]+"\" when executing "+
                      "\""+command+"\"");
            continue;
        }
    }

    tester.addResult(new JSHC.Test.TestResult(
        td.name,
        success,
        info.length==0 ? undefined : info.join("\n")));
};

////////////////////////////////////////////////////////////////////////////////
<commit_msg>testing: properly print error messages from compiler<commit_after>
// requires assertions

if( JSHC.Test === undefined ) JSHC.Test = {};
if( JSHC.Test.Cases === undefined) JSHC.Test.Cases = {};
////////////////////////////////////////////////////////////////////////////////

/*
  can be created with:
  (name, action)
  (name, action, obj) where 'obj' contains extra properties to copy
  (obj) where 'obj' contains properties to copy (including name and action)
*/
JSHC.Test.TestCase = function(p1, p2, p3){
    var k;

    if( typeof p1 === "string" && p2 instanceof Function ){
	this.name = p1;
	this.action = p2;
	for(k in p3){
	    if( k === "name" || k === "action" ){
		throw new Error("invalid parameters");
	    }
	    this[k] = p1[k];
	}
    } else if( p1 !== undefined &&
	       typeof p1.name === "string" &&
	       p1.action instanceof Function ) {
	for(k in p1){
	    this[k] = p1[k];
	}
    } else {
	throw new Error("invalid parameters");
    }
};

JSHC.Test.TestCase.prototype.result = function(ok, info){
    assert.ok( typeof ok === "boolean" && arguments.length <= 2 );
    return new JSHC.Test.TestResult(this, ok, info);
};

////////////////////////////////////////////////////////////////////////////////

JSHC.Test.TestResult = function(id, ok, info){
    assert.ok( typeof ok == "boolean" );
    if( typeof id == "string" ){
        this.name = id;
    } else if( id instanceof JSHC.Test.TestCase ){
        this.tc = id;
    }
    this.ok = ok;
    if( info !== undefined ){
        assert.ok( typeof info == "string", "test result \""+this.getName()+"\" has a non-string as info");
	this.info = info;
    }
};

JSHC.Test.TestResult.prototype.getName = function(){
    return this.name !== undefined ? this.name : this.tc.name;
};

////////////////////////////////////////////////////////////////////////////////

JSHC.Test.Tester = function(){
    this.results = {};
    this.passed = 0;
    this.failed = 0;
    this.interpreter = new JSHC.Interpreter("JSHC.Test.modules");
};

/*
  Makes a depth-first traversal over the test cases, and runs them.
*/
JSHC.Test.Tester.prototype.run = function(tests){
    var t;

    // run the single test case
    if( tests instanceof JSHC.Test.TestCase ){
	this.runTC(tests);
    } else if( tests instanceof Function ){
        this.runFunction(tests);
    } else {
        // run all test cases in the object
        for(t in tests){
	    this.run(tests[t]);
        }
    }
};

JSHC.Test.Tester.prototype.addResult = function(result){
    assert.ok( result instanceof JSHC.Test.TestResult );
    var name = result.getName();
    if( this.results[name] !== undefined ){
        throw new Error("test names overlap. \""+name+"\" exists more than once.");
    }
    this.results[name] = result;
    if( result.ok ){
        this.passed++;
    } else {
        this.failed++;
    }
};

/*
  Runs a single test case.
*/
JSHC.Test.Tester.prototype.runFunction = function(fun){
    assert.ok( fun instanceof Function );

    //tester = this;
    //var resultHandler = function(result){
    //    tester.addResult(result);
    //};

    fun(this);
};

/*
  Runs a single test case.
*/
JSHC.Test.Tester.prototype.runTC = function(tc){
    assert.ok( tc instanceof JSHC.Test.TestCase );
    this.addResult(tc.action());
};

/*
  Shows test results.
*/
JSHC.Test.Tester.prototype.toString = function(tc){
    var rn,msg = [];
    msg.push("tests passed:" + this.passed + "\n");
    msg.push("tests failed:" + this.failed + "\n");
    msg.push("\n");
    for(rn in this.results){
	var r = this.results[rn];
	assert.ok( r instanceof JSHC.Test.TestResult );

	// ignore passed tests
	if( r.ok )continue;

	// show failed tests
	msg.push("name: "+r.name+"\n");
	if( r.info === undefined || r.info.length == 0 ){
	    msg.push("(no information)");
	} else {
            msg.push(r.info);
	}
	msg.push("\n\n");
    }
    return msg.join("");
};

/*
  Shows test results.
*/
JSHC.Test.Tester.prototype.toHTML = function(tc){
    var rn,msg = [];
    msg.push("
tests passed:" + this.passed + "
");
    msg.push("tests failed:" + this.failed + "
");
    msg.push("

");
    for(rn in this.results){
	var r = this.results[rn];
	assert.ok( r instanceof JSHC.Test.TestResult );

	// ignore passed tests
	if( r.ok )continue;

	// show failed tests
	msg.push("name: "+r.getName()+"
");
	if( r.info === undefined || r.info.length == 0 ){
	    msg.push("(no information)");
	} else {
            // TODO: should somehow convert to HTML ?
            msg.push(r.info.replace(/\n/g,"
"));
	}
	msg.push("
");
    }
    return msg.join("");
};

////////////////////////////////////////////////////////////////////////////////

/*
  Runs the given tests and returns a string describing the results.
*/
JSHC.Test.runtests = function(tests, showHTML){
    var tester = new JSHC.Test.Tester();
    tester.run(tests);
    return showHTML ? tester.toHTML() : tester.toString();
};

////////////////////////////////////////////////////////////////////////////////

/*
  run test tests using test data
*/
JSHC.Test.runData = function(tester,td){
    assert.ok( td.fileSystem !== undefined );

    // set file system
    tester.interpreter.compiler.setFileSystem(td.fileSystem);

    // set targets
    if( td.targets === undefined ){
       var targets = [];
       for(var modname in td.fileSystem){
          targets.push(modname);
       }
    } else {
       targets = td.targets;
    }
    tester.interpreter.compiler.setTargets(targets);

    // compile
    tester.interpreter.compiler.recompile();

    var errorAmount;
    if( td.errors === undefined ){
        errorAmount = 0;
    } else {
        errorAmount = td.errors;
    }

    var info = [];
    if( tester.interpreter.errors !== errorAmount ){
        for(var i=0 ; i<tester.interpreter.errorList.length ; i++){
            var err = tester.interpreter.errorList[i];
            if( typeof err !== "string" ){
                err = JSHC.showError(err);
            }
            info.push(err);
        }
    }

    var success = tester.interpreter.errors === errorAmount;

    var commands = td.commands;
    for(var command in commands){
        tester.interpreter.execCommand(command);
        if( tester.interpreter.errors > 0 ){
            info.push(tester.interpreter.messageList.join("\n"));
            continue;
        }
        if ( tester.interpreter.messageList.length === 0 ) {
            success = false;
            info.push("got no result when executing\""+command+"\"");
            info.push(tester.interpreter.messageList.join("\n"));
            continue;
        }
        if( tester.interpreter.messageList.length !== 1 ){
            success = false;
            info.push("got more than one result when executing \""+command+"\":");
            info.push(tester.interpreter.messageList.join("\n"));
            continue;
        }
        if( tester.interpreter.messageList[0] !== commands[command] ){
            success = false;
            info.push("got result \""+tester.interpreter.messageList[0]+"\""+
                      " instead of \""+commands[command]+"\" when executing "+
                      "\""+command+"\"");
            continue;
        }
    }

    tester.addResult(new JSHC.Test.TestResult(
        td.name,
        success,
        info.length==0 ? undefined : info.join("\n")));
};

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>