<commit_before>(function(taskTracker){

  taskTracker.ControlMessages = function(){
    this.actions_container = $('table.tasks-list tr td.actions');
    this.new_name_container = $('.new_task table.tasks-list tr td.name');
    this.name_container = $('table.tasks-list tr td.name').not(this.new_name_container);
    this.todo_tasks_container = $('.todo_tasks table.tasks-list');
    this.timeoutID;
    this._bindEvents();
  }

  var proto = taskTracker.ControlMessages.prototype;

  proto._bindEvents = function(){
    this._completeTask();
    this._uncompleteTask();
    this._removeTask();
    this._restoreTask();
    this._restoreAllTask();
    this._editTask();
    this._newTask();
    this._dragTask();
    this._editGroup();
    this._newGroup();
    this._removeGroup();
  }

  proto._completeTask = function(){
    $('.row').on('ajax:success', 'table.tasks-list tr td.actions .complete', function(e, data, status, xhr){
      taskTracker.update_flash(data.message);
      self = e.target;
      uncomplete_path = $(self).attr('data-url-uncomplete');
      $(self).data('url', uncomplete_path);
      $(self).attr('class', 'uncomplete');
      $(self).removeClass('complete').addClass('uncomplete');
      done_tab = $(self).parents('.todo_tasks').next().find('table');
      $(self).parents('tr').slideUp('fast', function(){
        $(this).appendTo(done_tab).show();
        $('.container .row').trigger('applyWookmark');
      });
    }.bind(this));
  }

  proto._uncompleteTask = function(){
    $('.row').on('ajax:success', 'table.tasks-list tr td.actions .uncomplete', function(e, data, status, xhr){
      taskTracker.update_flash(data.message);
      self = e.target;
      complete_path = $(self).attr('data-url-complete');
      $(self).data('url', complete_path);
      $(self).removeClass('uncomplete').addClass('complete');
      todo_tab = $(self).parents('.done_tasks').prev().find('table');
      $(self).parents('tr').slideUp('fast', function(){
        $(this).appendTo(todo_tab).show();
        $('.container .row').trigger('applyWookmark');
      });
    }.bind(this));
  }

  proto._removeTask = function(){
    $('.row').on('ajax:success', 'table.tasks-list tr td.actions .remove', function(e, data, status, xhr){
      self = e.target
      $(self).parent().parent().remove();
      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._editTask = function(){
    $('.row').on('click', 'table.tasks-list tr td.name', function(){
      $(this).find('.text-holder').hide();
      $(this).find('.form-holder').show();
      $(this).find('.form-holder').find('input').focus();
    });

    $('.row').on('blur', 'table.tasks-list tr td.name .form-holder input', function(){
      var container = $(this).parents('td.name');

      container.find('.text-holder').show();
      container.find('.form-holder').hide();
    });

    $('.row').on('ajax:success', 'table.tasks-list tr td.name', function(e, data, status, xhr){
      container = $(e.target).parents('td.name');
      var text = container.find('.form-holder input:text').val();

      container.find('.text-holder').text(text).show();
      container.find('.form-holder').hide();

      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._newTask = function(){
    $('.row').on("ajax:success", '.new_task table.tasks-list tr td.name', function(e, data, status, xhr){
      var todo_tasks_container = $(this).parents('.new_task').prev().prev().find('table');
      $(this).find('input[name="task[name]"]').val('');

      $.get('tasks/' + data.task.id + '/html', function(data){
        todo_tasks_container.append(data);

        $('.container .row').trigger('applyWookmark');
        taskTracker.update_flash(data.message);
      });

    });
  }

  proto._dragTask = function(){
    $(document).on('ready page:load', function(){
      this.dragFunction($('body'));
    }.bind(this));
  }

  proto._restoreTask = function(){
    $('table#tasks-list tr td a#restore').on("ajax:success", function(e, data, status, xhr){
      self = e.target
      $(self).parent().parent().remove();
      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._restoreAllTask = function(){
    $('a#permanently_remove_tasks').on("ajax:success", function(e, data, status, xhr){
      taskTracker.update_flash(data.message);
      self = e.target
      $('table#tasks-list').remove();
    }.bind(this));
  }

  proto._editGroup = function(){
    $('.row').on('click', '.task-group:not(.new) .group-name', function(){
      $(this).find('.text-holder').hide();
      $(this).find('.form-holder').show();
      $(this).find('.form-holder').find('input').focus();
    });

    $('.row').on('blur', ' .task-group:not(.new) .group-name .form-holder input', function(){
      var container = $(this).parents('.group-name');
      container.find('.text-holder').show();
      container.find('.form-holder').hide();
    });

    $('.row').on('ajax:success', '.task-group:not(.new) .group-name', function(e, data, status, xhr){
      container = $(e.target).parents('.group-name');
      var text = container.find('.form-holder input:text').val();

      container.find('.text-holder').text(text).show();
      container.find('.form-holder').hide();

      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._newGroup = function(){
    $('.task-group.new').on('ajax:success', function(e, data, status, xhr){
      self = e.target;
      var group_container = $(self).parents('.task-group.new');

      group_container.find('input[name="group[name]"]').val('');

      $.get('groups/' + data.group.id + '/html', function(data){
        var $data = $(data);

        $($data).insertBefore(group_container);
        this.dragFunction($data);

        $('.container .row').trigger('applyWookmark');
      }.bind(this));

      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto.dragFunction = function(data){
    $(data.find(".todo_tasks .tasks-list tbody")).sortable({
      connectWith: '.todo_tasks .tasks-list tbody',
      placeholder: 'placeholder',
      cancel: 'tr.initial-placeholder',
      receive: function(event, ui){
        var sender_group_id =  ui.sender.parents('.todo_tasks').data('group-id');
        var receiver_group_id =  ui.item.parents('.todo_tasks').data('group-id');
        var task_id =  ui.item.data('task-id');

        // console.log(ui);
        // console.log('sender: ' + sender_group_id);
        // console.log('receiver: ' + receiver_group_id);

        $.ajax({
          url: 'tasks/' + task_id,
          data: { task: { group_id: receiver_group_id }},
          type: 'PUT',
          success: function(data) {
            $('.container .row').trigger('applyWookmark');

            taskTracker.update_flash(data.message);
          }
        });
      },
      stop: function(event, ui){
        var item                = ui.item;
        var next_itens          = item.nextAll();
        var receiver_group_id   = item.parents('.todo_tasks').data('group-id');
        var current_task_id     = item.data('task-id');
        var next_tasks_id       = new Array();
        var current_item_order  = 0;

        var prior_item = item.prev().not('.initial-placeholder');
        var next_item = item.next().not('.initial-placeholder');

        if (prior_item.length){
          current_item_order = prior_item.data('task-order') + 1;
        } else if(next_item.length) {
          current_item_order = next_item.data('task-order') - 1;
        }

        item.data('task-order', current_item_order);

        next_itens.each(function(index, item){
          next_tasks_id.push($(item).data('task-id'));
          $(item).data('task-order', $(item).data('task-order') + 1);
        });

        var params = {
          current_order: current_item_order,
          current_task_id: current_task_id,
          next_tasks_id: next_tasks_id
        };

        $.ajax({
          url: 'groups/' + receiver_group_id + '/increment_tasks',
          data: params,
          type: 'PUT',
          success: function(data) {
          }
        });
      }
    });
  }

  proto._removeGroup = function(){
    $('.row').on('ajax:success', '.task-group .remove-group', function(e, data, status, xhr){
      $(this).parents('.task-group').remove()

        $('.container .row').trigger('applyWookmark');
      taskTracker.update_flash(data.message);
    });
  }
})(taskTracker);
<commit_msg>Refactory tasks sort<commit_after>(function(taskTracker){

  taskTracker.ControlMessages = function(){
    this.actions_container = $('table.tasks-list tr td.actions');
    this.new_name_container = $('.new_task table.tasks-list tr td.name');
    this.name_container = $('table.tasks-list tr td.name').not(this.new_name_container);
    this.todo_tasks_container = $('.todo_tasks table.tasks-list');
    this.timeoutID;
    this._bindEvents();
  }

  var proto = taskTracker.ControlMessages.prototype;

  proto._bindEvents = function(){
    this._completeTask();
    this._uncompleteTask();
    this._removeTask();
    this._restoreTask();
    this._restoreAllTask();
    this._editTask();
    this._newTask();
    this._dragTask();
    this._editGroup();
    this._newGroup();
    this._removeGroup();
  }

  proto._completeTask = function(){
    $('.row').on('ajax:success', 'table.tasks-list tr td.actions .complete', function(e, data, status, xhr){
      taskTracker.update_flash(data.message);
      self = e.target;
      uncomplete_path = $(self).attr('data-url-uncomplete');
      $(self).data('url', uncomplete_path);
      $(self).attr('class', 'uncomplete');
      $(self).removeClass('complete').addClass('uncomplete');
      done_tab = $(self).parents('.todo_tasks').next().find('table');
      $(self).parents('tr').slideUp('fast', function(){
        $(this).appendTo(done_tab).show();
        $('.container .row').trigger('applyWookmark');
      });
    }.bind(this));
  }

  proto._uncompleteTask = function(){
    $('.row').on('ajax:success', 'table.tasks-list tr td.actions .uncomplete', function(e, data, status, xhr){
      taskTracker.update_flash(data.message);
      self = e.target;
      complete_path = $(self).attr('data-url-complete');
      $(self).data('url', complete_path);
      $(self).removeClass('uncomplete').addClass('complete');
      todo_tab = $(self).parents('.done_tasks').prev().find('table');
      $(self).parents('tr').slideUp('fast', function(){
        $(this).appendTo(todo_tab).show();
        $('.container .row').trigger('applyWookmark');
      });
    }.bind(this));
  }

  proto._removeTask = function(){
    $('.row').on('ajax:success', 'table.tasks-list tr td.actions .remove', function(e, data, status, xhr){
      self = e.target
      $(self).parent().parent().remove();
      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._editTask = function(){
    $('.row').on('click', 'table.tasks-list tr td.name', function(){
      $(this).find('.text-holder').hide();
      $(this).find('.form-holder').show();
      $(this).find('.form-holder').find('input').focus();
    });

    $('.row').on('blur', 'table.tasks-list tr td.name .form-holder input', function(){
      var container = $(this).parents('td.name');

      container.find('.text-holder').show();
      container.find('.form-holder').hide();
    });

    $('.row').on('ajax:success', 'table.tasks-list tr td.name', function(e, data, status, xhr){
      container = $(e.target).parents('td.name');
      var text = container.find('.form-holder input:text').val();

      container.find('.text-holder').text(text).show();
      container.find('.form-holder').hide();

      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._newTask = function(){
    $('.row').on("ajax:success", '.new_task table.tasks-list tr td.name', function(e, data, status, xhr){
      var todo_tasks_container = $(this).parents('.new_task').prev().prev().find('table');
      $(this).find('input[name="task[name]"]').val('');

      $.get('tasks/' + data.task.id + '/html', function(data){
        todo_tasks_container.append(data);

        $('.container .row').trigger('applyWookmark');
        taskTracker.update_flash(data.message);
      });

    });
  }

  proto._dragTask = function(){
    $(document).on('ready page:load', function(){
      this.dragFunction($('body'));
    }.bind(this));
  }

  proto._restoreTask = function(){
    $('table#tasks-list tr td a#restore').on("ajax:success", function(e, data, status, xhr){
      self = e.target
      $(self).parent().parent().remove();
      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._restoreAllTask = function(){
    $('a#permanently_remove_tasks').on("ajax:success", function(e, data, status, xhr){
      taskTracker.update_flash(data.message);
      self = e.target
      $('table#tasks-list').remove();
    }.bind(this));
  }

  proto._editGroup = function(){
    $('.row').on('click', '.task-group:not(.new) .group-name', function(){
      $(this).find('.text-holder').hide();
      $(this).find('.form-holder').show();
      $(this).find('.form-holder').find('input').focus();
    });

    $('.row').on('blur', ' .task-group:not(.new) .group-name .form-holder input', function(){
      var container = $(this).parents('.group-name');
      container.find('.text-holder').show();
      container.find('.form-holder').hide();
    });

    $('.row').on('ajax:success', '.task-group:not(.new) .group-name', function(e, data, status, xhr){
      container = $(e.target).parents('.group-name');
      var text = container.find('.form-holder input:text').val();

      container.find('.text-holder').text(text).show();
      container.find('.form-holder').hide();

      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto._newGroup = function(){
    $('.task-group.new').on('ajax:success', function(e, data, status, xhr){
      self = e.target;
      var group_container = $(self).parents('.task-group.new');

      group_container.find('input[name="group[name]"]').val('');

      $.get('groups/' + data.group.id + '/html', function(data){
        var $data = $(data);

        $($data).insertBefore(group_container);
        this.dragFunction($data);

        $('.container .row').trigger('applyWookmark');
      }.bind(this));

      taskTracker.update_flash(data.message);
    }.bind(this));
  }

  proto.dragFunction = function(data){
    $(data.find(".todo_tasks .tasks-list tbody")).sortable({
      connectWith: '.todo_tasks .tasks-list tbody',
      placeholder: 'placeholder',
      cancel: 'tr.initial-placeholder',
      receive: function(event, ui){
        var sender_group_id =  ui.sender.parents('.todo_tasks').data('group-id');
        var receiver_group_id =  ui.item.parents('.todo_tasks').data('group-id');
        var task_id = ui.item.data('task-id');

        $.ajax({
          url: 'tasks/' + task_id,
          data: { task: { group_id: receiver_group_id }},
          type: 'PUT',
          success: function(data) {
            $('.container .row').trigger('applyWookmark');
            taskTracker.update_flash(data.message);
          }
        });
      },
      stop: function(event, ui){
        var item                = ui.item;
        var next_itens          = item.nextAll();
        var receiver_group_id   = item.parents('.todo_tasks').data('group-id');
        var current_task_id     = item.data('task-id');
        var next_tasks_id       = new Array();
        var current_item_order  = 0;

        var prior_item = item.prev().not('.initial-placeholder');
        var next_item = item.next().not('.initial-placeholder');

        if (next_item.length){
          current_item_order = next_item.data('task-order');
        } else if (prior_item.length) {
          current_item_order = prior_item.data('task-order') + 1;
        }

        item.data('task-order', current_item_order);

        next_itens.each(function(index, item){
          next_tasks_id.push($(item).data('task-id'));
          $(item).data('task-order', $(item).data('task-order') + 1);
        });

        var params = {
          current_order: current_item_order,
          current_task_id: current_task_id,
          tasks_id: next_tasks_id
        };

        $.ajax({
          url: 'groups/' + receiver_group_id + '/increment_tasks',
          data: params,
          type: 'PUT',
          success: function(data) {
          }
        });
      }
    });
  }

  proto._removeGroup = function(){
    $('.row').on('ajax:success', '.task-group .remove-group', function(e, data, status, xhr){
      $(this).parents('.task-group').remove()

        $('.container .row').trigger('applyWookmark');
      taskTracker.update_flash(data.message);
    });
  }
})(taskTracker);
<|endoftext|>


<commit_before>CodeOceanEditorEvaluation = {
  chunkBuffer: [{streamedResponse: true}],

  /**
   * Scoring-Functions
   */
  scoreCode: function (event) {
    event.preventDefault();
    this.clearScoringOutput();
    $('#submit').addClass("d-none");
    this.createSubmission('#assess', null, function (response) {
      this.showSpinner($('#assess'));
      $('#score_div').removeClass('d-none');
      var url = response.score_url;
      this.initializeSocketForScoring(url);
    }.bind(this));
  },

  handleScoringResponse: function (results) {
    this.printScoringResults(results);
    var score = _.reduce(results, function (sum, result) {
      return sum + result.score * result.weight;
    }, 0).toFixed(2);
    $('#score').data('score', score);
    this.renderScore();
    $('#submit').removeClass("d-none");
  },

  printScoringResult: function (result, index) {
    $('#results').show();
    var card = $('#dummies').children().first().clone();
    if (card.isPresent()) {
        // the card won't be present if @embed_options[:hide_test_results] == true
        this.populateCard(card, result, index);
        $('#results ul').first().append(card);
    }
  },

  printScoringResults: function (response) {
    $('#results ul').first().html('');
    $('.test-count .number').html(response.length);
    this.clearOutput();

    _.each(response, function (result, index) {
      this.printOutput(result, false, index);
      this.printScoringResult(result, index);
    }.bind(this));

    if (_.some(response, function (result) {
          return result.status === 'timeout';
        })) {
      this.showTimeoutMessage();
    }
    if (_.some(response, function (result) {
          return result.status === 'container_depleted';
        })) {
      this.showContainerDepletedMessage();
    }
    if (this.qa_api) {
      // send test response to QA
      this.qa_api.executeCommand('syncOutput', [response]);
    }
  },

  renderScore: function () {
    var score = parseFloat($('#score').data('score'));
    var maximum_score = parseFloat($('#score').data('maximum-score'));
    if (score >= 0 && score <= maximum_score && maximum_score > 0) {
      var percentage_score = (score / maximum_score * 100 ).toFixed(0);
      $('.score').html(percentage_score + '%');
    }
    else {
      $('.score').html(0 + '%');
    }
    this.renderProgressBar(score, maximum_score);
  },

  /**
   * Testing-Logic
   */
  handleTestResponse: function (result) {
    this.clearOutput();
    this.printOutput(result, false, 0);
    if (this.qa_api) {
      this.qa_api.executeCommand('syncOutput', [result]);
    }
    this.showStatus(result);
    this.showOutputBar();
  },

  /**
   * Stop-Logic
   */
  stopCode: function (event) {
    event.preventDefault();
    if (this.isActiveFileStoppable()) {
      this.websocket.send(JSON.stringify({'cmd': 'client_kill'}));
      this.killWebsocket();
      this.cleanUpUI();
    }
  },

  killWebsocket: function () {
    if (this.websocket != null && this.websocket.getReadyState() != WebSocket.OPEN) {
      return;
    }

    this.websocket.killWebSocket();
    this.running = false;
  },

  cleanUpUI: function() {
    this.hideSpinner();
    this.toggleButtonStates();
    this.hidePrompt();
  },

  /**
   * Output-Logic
   */
  renderWebsocketOutput: function(msg){
    var element = this.findOrCreateRenderElement(0);
    element.append(msg.data);
  },

  printWebsocketOutput: function(msg) {
    if (!msg.data) {
      return;
    }
    msg.data = msg.data.replace(/(\r)/gm, "\n");
    var stream = {};
    stream[msg.stream] = msg.data;
    this.printOutput(stream, true, 0);
  },

  clearOutput: function() {
    $('#output pre').remove();
  },

  clearScoringOutput: function() {
    $('#results ul').first().html('');
    $('.test-count .number').html(0);
    $('#score').data('score', 0);
    this.renderScore();
    this.clearOutput();
  },

  printOutput: function (output, colorize, index) {
    if (output.stderr === undefined && output.stdout === undefined) {
        // Prevent empty element with no text at all
        return;
    }

    var element = this.findOrCreateOutputElement(index);
    // Switch all four lines below to enable the output of images and render <IMG/> tags
    if (!colorize) {
      if (output.stdout !== undefined && output.stdout !== '') {
        //element.append(output.stdout)
        element.text(element.text() + output.stdout)
      }

      if (output.stderr !== undefined && output.stderr !== '') {
        //element.append('StdErr: ' + output.stderr);
        element.text('StdErr: ' + element.text() + output.stderr);
      }

    } else if (output.stderr) {
        //element.addClass('text-warning').append(output.stderr);
        element.addClass('text-warning').text(element.text() + output.stderr);
      this.QaApiOutputBuffer.stderr += output.stderr;
    } else if (output.stdout) {
        //element.addClass('text-success').append(output.stdout);
        element.addClass('text-success').text(element.text() + output.stdout);
      this.QaApiOutputBuffer.stdout += output.stdout;
    } else {
      element.addClass('text-muted').text($('#output').data('message-no-output'));
    }
  }

};
<commit_msg>Set onError binding to underscore's no-op<commit_after>CodeOceanEditorEvaluation = {
  chunkBuffer: [{streamedResponse: true}],

  /**
   * Scoring-Functions
   */
  scoreCode: function (event) {
    event.preventDefault();
    this.clearScoringOutput();
    $('#submit').addClass("d-none");
    this.createSubmission('#assess', null, function (response) {
      this.showSpinner($('#assess'));
      $('#score_div').removeClass('d-none');
      var url = response.score_url;
      this.initializeSocketForScoring(url);
    }.bind(this));
  },

  handleScoringResponse: function (results) {
    this.printScoringResults(results);
    var score = _.reduce(results, function (sum, result) {
      return sum + result.score * result.weight;
    }, 0).toFixed(2);
    $('#score').data('score', score);
    this.renderScore();
    $('#submit').removeClass("d-none");
  },

  printScoringResult: function (result, index) {
    $('#results').show();
    var card = $('#dummies').children().first().clone();
    if (card.isPresent()) {
        // the card won't be present if @embed_options[:hide_test_results] == true
        this.populateCard(card, result, index);
        $('#results ul').first().append(card);
    }
  },

  printScoringResults: function (response) {
    $('#results ul').first().html('');
    $('.test-count .number').html(response.length);
    this.clearOutput();

    _.each(response, function (result, index) {
      this.printOutput(result, false, index);
      this.printScoringResult(result, index);
    }.bind(this));

    if (_.some(response, function (result) {
          return result.status === 'timeout';
        })) {
      this.showTimeoutMessage();
    }
    if (_.some(response, function (result) {
          return result.status === 'container_depleted';
        })) {
      this.showContainerDepletedMessage();
    }
    if (this.qa_api) {
      // send test response to QA
      this.qa_api.executeCommand('syncOutput', [response]);
    }
  },

  renderScore: function () {
    var score = parseFloat($('#score').data('score'));
    var maximum_score = parseFloat($('#score').data('maximum-score'));
    if (score >= 0 && score <= maximum_score && maximum_score > 0) {
      var percentage_score = (score / maximum_score * 100 ).toFixed(0);
      $('.score').html(percentage_score + '%');
    }
    else {
      $('.score').html(0 + '%');
    }
    this.renderProgressBar(score, maximum_score);
  },

  /**
   * Testing-Logic
   */
  handleTestResponse: function (result) {
    this.clearOutput();
    this.printOutput(result, false, 0);
    if (this.qa_api) {
      this.qa_api.executeCommand('syncOutput', [result]);
    }
    this.showStatus(result);
    this.showOutputBar();
  },

  /**
   * Stop-Logic
   */
  stopCode: function (event) {
    event.preventDefault();
    if (this.isActiveFileStoppable()) {
      this.websocket.send(JSON.stringify({'cmd': 'client_kill'}));
      this.killWebsocket();
      this.cleanUpUI();
    }
  },

  killWebsocket: function () {
    if (this.websocket != null && this.websocket.getReadyState() != WebSocket.OPEN) {
      return;
    }

    this.websocket.killWebSocket();
    this.websocket.onError(_.noop);
    this.running = false;
  },

  cleanUpUI: function() {
    this.hideSpinner();
    this.toggleButtonStates();
    this.hidePrompt();
  },

  /**
   * Output-Logic
   */
  renderWebsocketOutput: function(msg){
    var element = this.findOrCreateRenderElement(0);
    element.append(msg.data);
  },

  printWebsocketOutput: function(msg) {
    if (!msg.data) {
      return;
    }
    msg.data = msg.data.replace(/(\r)/gm, "\n");
    var stream = {};
    stream[msg.stream] = msg.data;
    this.printOutput(stream, true, 0);
  },

  clearOutput: function() {
    $('#output pre').remove();
  },

  clearScoringOutput: function() {
    $('#results ul').first().html('');
    $('.test-count .number').html(0);
    $('#score').data('score', 0);
    this.renderScore();
    this.clearOutput();
  },

  printOutput: function (output, colorize, index) {
    if (output.stderr === undefined && output.stdout === undefined) {
        // Prevent empty element with no text at all
        return;
    }

    var element = this.findOrCreateOutputElement(index);
    // Switch all four lines below to enable the output of images and render <IMG/> tags
    if (!colorize) {
      if (output.stdout !== undefined && output.stdout !== '') {
        //element.append(output.stdout)
        element.text(element.text() + output.stdout)
      }

      if (output.stderr !== undefined && output.stderr !== '') {
        //element.append('StdErr: ' + output.stderr);
        element.text('StdErr: ' + element.text() + output.stderr);
      }

    } else if (output.stderr) {
        //element.addClass('text-warning').append(output.stderr);
        element.addClass('text-warning').text(element.text() + output.stderr);
      this.QaApiOutputBuffer.stderr += output.stderr;
    } else if (output.stdout) {
        //element.addClass('text-success').append(output.stdout);
        element.addClass('text-success').text(element.text() + output.stdout);
      this.QaApiOutputBuffer.stdout += output.stdout;
    } else {
      element.addClass('text-muted').text($('#output').data('message-no-output'));
    }
  }

};
<|endoftext|>


<commit_before>CodeOceanEditorEvaluation = {
    chunkBuffer: [{streamedResponse: true}],
    // A list of non-printable characters that are not allowed in the code output.
    // Taken from https://stackoverflow.com/a/69024306
    nonPrintableRegEx: /[\u0000-\u0008\u000B\u000C\u000F-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]/g,

    /**
     * Scoring-Functions
     */
    scoreCode: function (event) {
        event.preventDefault();
        this.stopCode(event);
        this.clearScoringOutput();
        $('#submit').addClass("d-none");
        this.createSubmission('#assess', null, function (response) {
            this.showSpinner($('#assess'));
            $('#score_div').removeClass('d-none');
            var url = response.score_url;
            this.initializeSocketForScoring(url);
        }.bind(this));
    },

    handleScoringResponse: function (results) {
        this.printScoringResults(results);
        var score = _.reduce(results, function (sum, result) {
            return sum + result.score * result.weight;
        }, 0).toFixed(2);
        $('#score').data('score', score);
        this.renderScore();
        this.showSubmitButton();
    },

    showSubmitButton: function () {
        if (this.submission_deadline || this.late_submission_deadline) {
            const now = new Date();
            if (now <= this.submission_deadline) {
                // before_deadline
                // default is btn-success, so no change in color
                $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_on_time');
            } else if (now > this.submission_deadline && this.late_submission_deadline && now <= this.late_submission_deadline) {
                // within_grace_period
                $('#submit').removeClass("btn-success btn-warning").addClass("btn-warning");
                $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_within_grace_period');
            } else if (this.late_submission_deadline && now > this.late_submission_deadline || now > this.submission_deadline) {
                // after_late_deadline
                $('#submit').removeClass("btn-success btn-warning btn-danger").addClass("btn-danger");
                $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_after_late_deadline');
            }
        }
        $('#submit').removeClass("d-none");
    },

    printScoringResult: function (result, index) {
        if (result === undefined || result === null) {
            return;
        }

        $('#results').show();
        let card;
        if (result.file_role === 'teacher_defined_linter') {
            card = $('#linter-dummies').children().first().clone();
        } else {
            card = $('#test-dummies').children().first().clone();
        }
        if (card.isPresent()) {
            // the card won't be present if @embed_options[:hide_test_results] == true
            this.populateCard(card, result, index);
            $('#results ul').first().append(card);
        }
    },

    printScoringResults: function (response) {
        response = (Array.isArray(response)) ? response : [response]
        const test_results = response.filter(function(x) {
            if (x === undefined || x === null) {
                return false;
            }
            switch (x.file_role) {
                case 'teacher_defined_test':
                    return true;
                case 'teacher_defined_linter':
                    return true;
                default:
                    return false;
            }
        });

        $('#results ul').first().html('');
        $('.test-count .number').html(test_results.length);
        this.clearOutput();

        _.each(test_results, function (result, index) {
            // based on https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
            if (result === Object(result)) {
                this.printOutput(result, false, index);
                this.printScoringResult(result, index);
            }
        }.bind(this));

        if (_.some(response, function (result) {
            return result.status === 'timeout';
        })) {
            this.showTimeoutMessage();
        }
        if (_.some(response, function (result) {
            return result.status === 'out_of_memory';
        })) {
            this.showOutOfMemoryMessage();
        }
        if (_.some(response, function (result) {
            return result.status === 'container_depleted';
        })) {
            this.showContainerDepletedMessage();
        }
        if (this.qa_api) {
            // send test response to QA
            this.qa_api.executeCommand('syncOutput', [response]);
        }
    },

    renderScore: function () {
        var score = parseFloat($('#score').data('score'));
        var maximum_score = parseFloat($('#score').data('maximum-score'));
        if (score >= 0 && score <= maximum_score && maximum_score > 0) {
            var percentage_score = (score / maximum_score * 100).toFixed(0);
            $('.score').html(percentage_score + '%');
        } else {
            $('.score').html(0 + '%');
        }
        this.renderProgressBar(score, maximum_score);
    },

    /**
     * Testing-Logic
     */
    handleTestResponse: function (result) {
        this.clearOutput();
        this.printOutput(result, false, 0);
        if (this.qa_api) {
            this.qa_api.executeCommand('syncOutput', [result]);
        }
        this.showStatus(result);
        this.showOutputBar();
    },

    /**
     * Stop-Logic
     */
    stopCode: function (event) {
        event.preventDefault();
        if (this.isActiveFileStoppable()) {
            this.websocket.send(JSON.stringify({'cmd': 'client_kill'}));
            this.killWebsocket();
            this.cleanUpUI();
        }
    },

    killWebsocket: function () {
        if (this.websocket != null && this.websocket.getReadyState() !== WebSocket.OPEN) {
            return;
        }

        this.websocket.killWebSocket();
        this.websocket.onError(_.noop);
        this.running = false;
    },

    cleanUpUI: function () {
        this.hideSpinner();
        this.toggleButtonStates();
        this.hidePrompt();
    },

    /**
     * Output-Logic
     */
    printWebsocketOutput: function (msg) {
        if (!msg.data || msg.data === "\r") {
            return;
        }
        var stream = {};
        stream[msg.stream] = msg.data;
        this.printOutput(stream, true, 0);
    },

    clearOutput: function () {
        $('#output > .output-element').remove();
        CodeOceanEditorTurtle.hideCanvas();
    },

    clearScoringOutput: function () {
        $('#results ul').first().html('');
        $('.test-count .number').html(0);
        $('#score').data('score', 0);
        this.renderScore();
        this.clearOutput();
    },

    printOutput: function (output, colorize, index) {
        if (output === undefined || output === null || output.stderr === undefined && output.stdout === undefined) {
            // Prevent empty element with no text at all
            return;
        }

        const sanitizedStdout = this.sanitizeOutput(output.stdout);
        const sanitizedStderr = this.sanitizeOutput(output.stderr);

        const element = this.findOrCreateOutputElement(index);
        const pre = $('<span>');

        if (sanitizedStdout !== '') {
            if (colorize) {
                pre.addClass('text-success');
            }
            pre.append(sanitizedStdout)
        }

        if (sanitizedStderr !== '') {
            if (colorize) {
                pre.addClass('text-warning');
            } else {
                pre.append('StdErr: ');
            }
            pre.append(sanitizedStderr);
        }

        if (sanitizedStdout === '' && sanitizedStderr === '') {
            if (colorize) {
                pre.addClass('text-muted');
            }
            pre.text($('#output').data('message-no-output'))
        }

        element.append(pre);
    },

    sanitizeOutput: function (rawContent) {
        let sanitizedContent = _.escape(rawContent).replace(this.nonPrintableRegEx, "");

        if (rawContent !== undefined && rawContent.trim().startsWith("<img")) {
            const doc = new DOMParser().parseFromString(rawContent, "text/html");
            // Get the parsed element, it is automatically wrapped in a <html><body> document
            const parsedElement = doc.firstChild.lastChild.firstChild;

            if (parsedElement.src.startsWith("data:image")) {
                const sanitizedImg = document.createElement('img');
                sanitizedImg.src = parsedElement.src;
                sanitizedContent = sanitizedImg.outerHTML;
            }
        }

        return sanitizedContent;
    },

    getDeadlineInformation: function(deadline, translation_key, otherwise) {
        if (deadline !== undefined) {
            let li = document.createElement("li");
            this.submission_deadline = new Date(deadline);
            let deadline_text = I18n.l("time.formats.long", this.submission_deadline);
            deadline_text += ` (${this.getUTCTime(this.submission_deadline, I18n.locale === 'en')})`;
            const bullet_point = I18n.t('exercises.editor.hints.' + translation_key,
                { deadline: deadline_text, otherwise: otherwise })
            let text = $.parseHTML(bullet_point);
            $(li).append(text);
            return li;
        }
    },

    getUTCTime: function(d, use_am_pm) {
        let hour = d.getUTCHours();
        const pm = hour >= 12;
        let hour12 = hour % 12;
        if (!hour12) {
            hour12 += 12;
        }
        hour = hour.toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping: false})
        const minute = d.getUTCMinutes().toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping: false})
        const second = d.getUTCSeconds().toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping: false})
        if (use_am_pm) {
            return `${hour12}:${minute}:${second} ${pm ? 'pm' : 'am'} UTC`;
        } else {
            return `${hour}:${minute}:${second} UTC`;
        }
    },

    initializeDeadlines: function () {
        const deadline = $('#deadline');
        if (deadline) {
            const submission_deadline = deadline.data('submission-deadline');
            const late_submission_deadline = deadline.data('late-submission-deadline');

            const ul = document.createElement("ul");

            if (submission_deadline && late_submission_deadline) {
                ul.append(this.getDeadlineInformation(submission_deadline, 'submission_deadline', ''));
                ul.append(this.getDeadlineInformation(late_submission_deadline, 'late_submission_deadline', ''));
            } else {
                const otherwise_no_points = I18n.t('exercises.editor.hints.otherwise');
                ul.append(this.getDeadlineInformation(submission_deadline, 'submission_deadline', otherwise_no_points));
            }

            $(ul).insertAfter($(deadline).children()[0]);
        }
    }
};
<commit_msg>Handle undefined `this.websocket` when stopping code<commit_after>CodeOceanEditorEvaluation = {
    chunkBuffer: [{streamedResponse: true}],
    // A list of non-printable characters that are not allowed in the code output.
    // Taken from https://stackoverflow.com/a/69024306
    nonPrintableRegEx: /[\u0000-\u0008\u000B\u000C\u000F-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]/g,

    /**
     * Scoring-Functions
     */
    scoreCode: function (event) {
        event.preventDefault();
        this.stopCode(event);
        this.clearScoringOutput();
        $('#submit').addClass("d-none");
        this.createSubmission('#assess', null, function (response) {
            this.showSpinner($('#assess'));
            $('#score_div').removeClass('d-none');
            var url = response.score_url;
            this.initializeSocketForScoring(url);
        }.bind(this));
    },

    handleScoringResponse: function (results) {
        this.printScoringResults(results);
        var score = _.reduce(results, function (sum, result) {
            return sum + result.score * result.weight;
        }, 0).toFixed(2);
        $('#score').data('score', score);
        this.renderScore();
        this.showSubmitButton();
    },

    showSubmitButton: function () {
        if (this.submission_deadline || this.late_submission_deadline) {
            const now = new Date();
            if (now <= this.submission_deadline) {
                // before_deadline
                // default is btn-success, so no change in color
                $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_on_time');
            } else if (now > this.submission_deadline && this.late_submission_deadline && now <= this.late_submission_deadline) {
                // within_grace_period
                $('#submit').removeClass("btn-success btn-warning").addClass("btn-warning");
                $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_within_grace_period');
            } else if (this.late_submission_deadline && now > this.late_submission_deadline || now > this.submission_deadline) {
                // after_late_deadline
                $('#submit').removeClass("btn-success btn-warning btn-danger").addClass("btn-danger");
                $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_after_late_deadline');
            }
        }
        $('#submit').removeClass("d-none");
    },

    printScoringResult: function (result, index) {
        if (result === undefined || result === null) {
            return;
        }

        $('#results').show();
        let card;
        if (result.file_role === 'teacher_defined_linter') {
            card = $('#linter-dummies').children().first().clone();
        } else {
            card = $('#test-dummies').children().first().clone();
        }
        if (card.isPresent()) {
            // the card won't be present if @embed_options[:hide_test_results] == true
            this.populateCard(card, result, index);
            $('#results ul').first().append(card);
        }
    },

    printScoringResults: function (response) {
        response = (Array.isArray(response)) ? response : [response]
        const test_results = response.filter(function(x) {
            if (x === undefined || x === null) {
                return false;
            }
            switch (x.file_role) {
                case 'teacher_defined_test':
                    return true;
                case 'teacher_defined_linter':
                    return true;
                default:
                    return false;
            }
        });

        $('#results ul').first().html('');
        $('.test-count .number').html(test_results.length);
        this.clearOutput();

        _.each(test_results, function (result, index) {
            // based on https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
            if (result === Object(result)) {
                this.printOutput(result, false, index);
                this.printScoringResult(result, index);
            }
        }.bind(this));

        if (_.some(response, function (result) {
            return result.status === 'timeout';
        })) {
            this.showTimeoutMessage();
        }
        if (_.some(response, function (result) {
            return result.status === 'out_of_memory';
        })) {
            this.showOutOfMemoryMessage();
        }
        if (_.some(response, function (result) {
            return result.status === 'container_depleted';
        })) {
            this.showContainerDepletedMessage();
        }
        if (this.qa_api) {
            // send test response to QA
            this.qa_api.executeCommand('syncOutput', [response]);
        }
    },

    renderScore: function () {
        var score = parseFloat($('#score').data('score'));
        var maximum_score = parseFloat($('#score').data('maximum-score'));
        if (score >= 0 && score <= maximum_score && maximum_score > 0) {
            var percentage_score = (score / maximum_score * 100).toFixed(0);
            $('.score').html(percentage_score + '%');
        } else {
            $('.score').html(0 + '%');
        }
        this.renderProgressBar(score, maximum_score);
    },

    /**
     * Testing-Logic
     */
    handleTestResponse: function (result) {
        this.clearOutput();
        this.printOutput(result, false, 0);
        if (this.qa_api) {
            this.qa_api.executeCommand('syncOutput', [result]);
        }
        this.showStatus(result);
        this.showOutputBar();
    },

    /**
     * Stop-Logic
     */
    stopCode: function (event) {
        event.preventDefault();
        if (this.isActiveFileStoppable() && this.websocket) {
            this.websocket.send(JSON.stringify({'cmd': 'client_kill'}));
            this.killWebsocket();
            this.cleanUpUI();
        }
    },

    killWebsocket: function () {
        if (this.websocket != null && this.websocket.getReadyState() !== WebSocket.OPEN) {
            return;
        }

        this.websocket.killWebSocket();
        this.websocket.onError(_.noop);
        this.running = false;
    },

    cleanUpUI: function () {
        this.hideSpinner();
        this.toggleButtonStates();
        this.hidePrompt();
    },

    /**
     * Output-Logic
     */
    printWebsocketOutput: function (msg) {
        if (!msg.data || msg.data === "\r") {
            return;
        }
        var stream = {};
        stream[msg.stream] = msg.data;
        this.printOutput(stream, true, 0);
    },

    clearOutput: function () {
        $('#output > .output-element').remove();
        CodeOceanEditorTurtle.hideCanvas();
    },

    clearScoringOutput: function () {
        $('#results ul').first().html('');
        $('.test-count .number').html(0);
        $('#score').data('score', 0);
        this.renderScore();
        this.clearOutput();
    },

    printOutput: function (output, colorize, index) {
        if (output === undefined || output === null || output.stderr === undefined && output.stdout === undefined) {
            // Prevent empty element with no text at all
            return;
        }

        const sanitizedStdout = this.sanitizeOutput(output.stdout);
        const sanitizedStderr = this.sanitizeOutput(output.stderr);

        const element = this.findOrCreateOutputElement(index);
        const pre = $('<span>');

        if (sanitizedStdout !== '') {
            if (colorize) {
                pre.addClass('text-success');
            }
            pre.append(sanitizedStdout)
        }

        if (sanitizedStderr !== '') {
            if (colorize) {
                pre.addClass('text-warning');
            } else {
                pre.append('StdErr: ');
            }
            pre.append(sanitizedStderr);
        }

        if (sanitizedStdout === '' && sanitizedStderr === '') {
            if (colorize) {
                pre.addClass('text-muted');
            }
            pre.text($('#output').data('message-no-output'))
        }

        element.append(pre);
    },

    sanitizeOutput: function (rawContent) {
        let sanitizedContent = _.escape(rawContent).replace(this.nonPrintableRegEx, "");

        if (rawContent !== undefined && rawContent.trim().startsWith("<img")) {
            const doc = new DOMParser().parseFromString(rawContent, "text/html");
            // Get the parsed element, it is automatically wrapped in a <html><body> document
            const parsedElement = doc.firstChild.lastChild.firstChild;

            if (parsedElement.src.startsWith("data:image")) {
                const sanitizedImg = document.createElement('img');
                sanitizedImg.src = parsedElement.src;
                sanitizedContent = sanitizedImg.outerHTML;
            }
        }

        return sanitizedContent;
    },

    getDeadlineInformation: function(deadline, translation_key, otherwise) {
        if (deadline !== undefined) {
            let li = document.createElement("li");
            this.submission_deadline = new Date(deadline);
            let deadline_text = I18n.l("time.formats.long", this.submission_deadline);
            deadline_text += ` (${this.getUTCTime(this.submission_deadline, I18n.locale === 'en')})`;
            const bullet_point = I18n.t('exercises.editor.hints.' + translation_key,
                { deadline: deadline_text, otherwise: otherwise })
            let text = $.parseHTML(bullet_point);
            $(li).append(text);
            return li;
        }
    },

    getUTCTime: function(d, use_am_pm) {
        let hour = d.getUTCHours();
        const pm = hour >= 12;
        let hour12 = hour % 12;
        if (!hour12) {
            hour12 += 12;
        }
        hour = hour.toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping: false})
        const minute = d.getUTCMinutes().toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping: false})
        const second = d.getUTCSeconds().toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping: false})
        if (use_am_pm) {
            return `${hour12}:${minute}:${second} ${pm ? 'pm' : 'am'} UTC`;
        } else {
            return `${hour}:${minute}:${second} UTC`;
        }
    },

    initializeDeadlines: function () {
        const deadline = $('#deadline');
        if (deadline) {
            const submission_deadline = deadline.data('submission-deadline');
            const late_submission_deadline = deadline.data('late-submission-deadline');

            const ul = document.createElement("ul");

            if (submission_deadline && late_submission_deadline) {
                ul.append(this.getDeadlineInformation(submission_deadline, 'submission_deadline', ''));
                ul.append(this.getDeadlineInformation(late_submission_deadline, 'late_submission_deadline', ''));
            } else {
                const otherwise_no_points = I18n.t('exercises.editor.hints.otherwise');
                ul.append(this.getDeadlineInformation(submission_deadline, 'submission_deadline', otherwise_no_points));
            }

            $(ul).insertAfter($(deadline).children()[0]);
        }
    }
};
<|endoftext|>


<commit_before>angular.module('scharwerk')
.controller('MarkupCtrl', [
'$scope',
'$state',
'tasks',
'task',
'$anchorScroll',
'$modal',
'$timeout',
function($scope, $state, tasks, task, $anchorScroll, $modal, $timeout){
  if (!tasks.current.exists) {
    $state.go('index');
    return ;
  }

  var editor = null;
  $scope.aceLoaded = function(_editor) {
    _editor.setFontSize(18);
    editor = _editor;
  };

  $scope.insertChar = function(char) {
    editor.insert(char);
    editor.focus();
  };

  $scope.insertTex = function(tex) {
    var s = tex.replace('#', editor.getSelectedText());
    editor.insert(s);
    editor.focus();
  };

  $scope.submitModal = function() {
    $modal.open({templateUrl: 'submitModal.html'}).result.then(function (getNext) {
      tasks.finish(getNext).success(function () {
        if (!getNext) {
          $state.go('index');
          return ;
        };

        updatePage(tasks.current.current_page);
      });
    });
  }

  $scope.releaseModal = function () {
    $modal.open({templateUrl: 'releaseModal.html'}).result.then(function () {
      tasks.release().success(function () {
        $state.go('index');
      });
    });
  }

  $scope.skipModal = function () {
    $modal.open({templateUrl: 'skipModal.html'}).result.then(function () {
      tasks.release(true).success(function () {
        updatePage(tasks.current.current_page);
      });
    });
  }

  var updateTex = function(task) {
    $scope.tex = tasks.current.tex;
    $scope.images = tasks.current.images;
    $scope.pages = tasks.current.pages;
  };

  updateTex(tasks.current);

  $scope.manualModal = function () {
    $modal.open({templateUrl: 'manuals/markup.html', size: 'small'});
  };

  $scope.preview = false;
  $scope.loading = false;

  $scope.showPreview = function () {
    $scope.preview = true;
    $scope.loading = true;
    // reset value from editor
    $scope.tex = editor.getValue();
    tasks.updateTex($scope.tex, true).success(function () {
      $scope.images = tasks.current.images;
      $scope.loading = false;
    });
  };

  $scope.hidePreview = function () {
    $scope.preview = false;
  };

  $scope.savedStatus = 'Зберегти';
  $scope.save = function() {
    tasks.updateTex($scope.tex, false).success(function () {
      $scope.savedStatus = 'Збережено.';
      $timeout(function () { $scope.savedStatus = 'Зберегти'; }, 1000);
    });
  }

  $scope.saveAndContinue = function() {
    tasks.savePage($scope.id, $scope.text, true).success(function() {
      updatePage(tasks.current.current_page);
    });
  }

  // $scope.manualModal();
}]);
<commit_msg>markup buttons<commit_after>angular.module('scharwerk')
.controller('MarkupCtrl', [
'$scope',
'$state',
'tasks',
'task',
'$anchorScroll',
'$modal',
'$timeout',
function($scope, $state, tasks, task, $anchorScroll, $modal, $timeout){
  if (!tasks.current.exists) {
    $state.go('index');
    return ;
  }

  var editor = null;
  $scope.aceLoaded = function(_editor) {
    _editor.setFontSize(18);
    editor = _editor;
  };

  $scope.insertChar = function(char) {
    editor.insert(char);
    editor.focus();
  };

  $scope.insertTex = function(tex) {
    var s = tex.replace('#', editor.getSelectedText());
    editor.insert(s);
    editor.focus();
  };

  $scope.submitModal = function() {
    $modal.open({templateUrl: 'submitModal.html'}).result.then(function (getNext) {
      tasks.finish(getNext).success(function () {
        if (!getNext) {
          $state.go('index');
          return ;
        };

        updateTex(tasks.current);
      });
    });
  }

  $scope.releaseModal = function () {
    $modal.open({templateUrl: 'releaseModal.html'}).result.then(function () {
      tasks.release().success(function () {
        $state.go('index');
      });
    });
  }

  $scope.skipModal = function () {
    $modal.open({templateUrl: 'skipModal.html'}).result.then(function () {
      tasks.release(true).success(function () {
        updateTex(tasks.current);
      });
    });
  }

  var updateTex = function(task) {
    $scope.tex = task.tex;
    $scope.images = {};
    $scope.pages = task.pages;

    $scope.preview = false;
    $scope.loading = false;
  };

  $scope.manualModal = function () {
    $modal.open({templateUrl: 'manuals/markup.html', size: 'small'});
  };

  $scope.showPreview = function () {
    $scope.preview = true;
    $scope.loading = true;
    // reset value from editor
    if (editor) {
      $scope.tex = editor.getValue();
    };
    tasks.updateTex($scope.tex, true).success(function () {
      $scope.images = tasks.current.images;
      $scope.loading = false;
    });
  };

  $scope.hidePreview = function () {
    $scope.preview = false;
  };

  $scope.savedStatus = 'Зберегти';
  $scope.save = function() {
    tasks.updateTex($scope.tex, false).success(function () {
      $scope.savedStatus = 'Збережено.';
      $timeout(function () { $scope.savedStatus = 'Зберегти'; }, 1000);
    });
  }

  updateTex(tasks.current);
  $scope.manualModal();
}]);
<|endoftext|>


<commit_before>import McFly from 'mcfly';
import BlockStore from './block_store.js';
const Flux = new McFly();

// Data
let _weeks = {};
const _persisted = {};
let _isLoading = true;

// Utilities
const setWeeks = function (data, persisted = false) {
  for (let i = 0; i < data.length; i++) {
    const week = data[i];
    _weeks[week.id] = week;
    if (persisted) { _persisted[week.id] = $.extend(true, {}, week); }
  }
  _isLoading = false;
  return WeekStore.emitChange();
};

const setWeek = function (data) {
  _weeks[data.id] = data;
  return WeekStore.emitChange();
};

const addWeek = () =>
  setWeek({
    id: Date.now(), // could THEORETICALLY collide but highly unlikely
    is_new: true, // remove ids from objects with is_new when persisting
    blocks: []
  });
const removeWeek = function (weekId) {
  delete _weeks[weekId];
  return WeekStore.emitChange();
};

const removeAllWeeks = function () {
  _weeks = {};
  return WeekStore.emitChange();
};

// Store
const WeekStore = Flux.createStore(
  {
    getLoadingStatus() {
      return _isLoading;
    },
    getWeek(weekId) {
      return _weeks[weekId];
    },
    getWeeks() {
      const weekList = [];
      const iterable = Object.keys(_weeks);
      for (let i = 0; i < iterable.length; i++) {
        const weekId = iterable[i];
        weekList.push(_weeks[weekId]);
      }
      return weekList;
    },
    restore() {
      _weeks = $.extend(true, {}, _persisted);
      return WeekStore.emitChange();
    },
  }
  , (payload) => {
    const { data } = payload;
    switch (payload.actionType) {
      case 'RECEIVE_TIMELINE': case 'SAVED_TIMELINE': case 'WIZARD_SUBMITTED':
        Flux.dispatcher.waitFor([BlockStore.dispatcherID]);
        _weeks = {};
        setWeeks(data.course.weeks, true);
        break;
      case 'ADD_WEEK':
        addWeek();
        break;
      case 'DELETE_WEEK':
        removeWeek(data.week_id);
        break;
      case 'DELETE_ALL_WEEKS':
        removeAllWeeks();
        break;
      default:
      // no default
    }
    return true;
  }
);

export default WeekStore;
<commit_msg>Fix glitchy Timeline when new weeks are added<commit_after>import McFly from 'mcfly';
import BlockStore from './block_store.js';
const Flux = new McFly();

// Data
let _weeks = {};
const _persisted = {};
let _isLoading = true;

// Utilities
const setWeeks = function (data, persisted = false) {
  for (let i = 0; i < data.length; i++) {
    const week = data[i];
    _weeks[week.id] = week;
    if (persisted) { _persisted[week.id] = $.extend(true, {}, week); }
  }
  _isLoading = false;
  return WeekStore.emitChange();
};

const setWeek = function (data) {
  _weeks[data.id] = data;
  return WeekStore.emitChange();
};

const addWeek = () =>
  setWeek({
    id: Date.now(), // could THEORETICALLY collide but highly unlikely
    is_new: true, // remove ids from objects with is_new when persisting
    blocks: [],
    order: WeekStore.getWeeks().length + 1
  });
const removeWeek = function (weekId) {
  delete _weeks[weekId];
  return WeekStore.emitChange();
};

const removeAllWeeks = function () {
  _weeks = {};
  return WeekStore.emitChange();
};

// Store
const WeekStore = Flux.createStore(
  {
    getLoadingStatus() {
      return _isLoading;
    },
    getWeek(weekId) {
      return _weeks[weekId];
    },
    getWeeks() {
      const weekList = [];
      const iterable = Object.keys(_weeks);
      for (let i = 0; i < iterable.length; i++) {
        const weekId = iterable[i];
        weekList.push(_weeks[weekId]);
      }
      return weekList;
    },
    restore() {
      _weeks = $.extend(true, {}, _persisted);
      return WeekStore.emitChange();
    },
  }
  , (payload) => {
    const { data } = payload;
    switch (payload.actionType) {
      case 'RECEIVE_TIMELINE': case 'SAVED_TIMELINE': case 'WIZARD_SUBMITTED':
        Flux.dispatcher.waitFor([BlockStore.dispatcherID]);
        _weeks = {};
        setWeeks(data.course.weeks, true);
        break;
      case 'ADD_WEEK':
        addWeek();
        break;
      case 'DELETE_WEEK':
        removeWeek(data.week_id);
        break;
      case 'DELETE_ALL_WEEKS':
        removeAllWeeks();
        break;
      default:
      // no default
    }
    return true;
  }
);

export default WeekStore;
<|endoftext|>


<commit_before>/**
 * @file This file is the main (i.e. body) javascript file of web worker. It is not
 * an importable module.
 *
 * In module (non-classic) web worker, static import is available. But at the same
 * time, importScripts() will not be avbailable. For solving this problem, using
 * classic (non-module) web worker so that some global library (e.g. tensorflow.js)
 * can be loaded by importScripts(). At the same time, using dynamic import() to
 * load ourselves module because import() can be used in classic (non-module) script.
 */

import( "./AsyncWorker_Body_tester.js" );

//!!! (2022/09/13 Remarked) use import() at global.
// ( async () => {
// //  await import( "./AsyncWorker_Body_tester.js" );
//   import( "./AsyncWorker_Body_tester.js" );
// } )();
<commit_msg>Improve comments.<commit_after>/**
 * @file This file is the main (i.e. body) javascript file of web worker. It is not
 * an importable module.
 *
 * In module (non-classic) web worker, static import is available. But at the same
 * time, importScripts() will not be avbailable. For solving this problem, using
 * classic (non-module) web worker so that some global library (e.g. tensorflow.js)
 * can be loaded by importScripts(). And use dynamic import() to load ourselves
 * modules because import() can be used in classic (non-module) script.
 */

import( "./AsyncWorker_Body_tester.js" );

//!!! (2022/09/13 Remarked) use import() at global.
// ( async () => {
// //  await import( "./AsyncWorker_Body_tester.js" );
//   import( "./AsyncWorker_Body_tester.js" );
// } )();
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

angular.module('main.controllers', ['main.services'])
  .controller('UserController', function($scope, $rootScope, $timeout, $q, APIService) {
    $scope.refreshInterval = 5;
    $scope.refreshUser = function(){
      // Return a function that will keep refreshing the feeds
      var promise = APIService.getUser().then(function(user){
        $scope.user = user;
      });
      //$timeout(function(){$scope.refreshUser();}, $scope.refreshInterval * 1000);
      // I have no idea where this returns to when the function calls itself, and what
      // Angular does to garbage collect. But it works.
      return promise;
    };
    $scope.getTopicIds = function(){
      if (this.user == null){
        // Force a refresh
        var promise = $scope.refreshUser().then(function(){
          return $scope.user["topics"];
        });
        return promise;
      }
      else{
        // Return a promise that we can resolve immediately
        var deferred = $q.defer();
        deferred.resolve($scope.user["topics"]);
        return deferred.promise;
      }
    };
  })
  .controller('NavigationController', function($scope, $rootScope, $timeout, APIService) {
    $scope.topics = [];
    $scope.topicIds = [];

    // Event handlers

    // when addedTopic event is fired
    $rootScope.$on("addedTopic", function (event, message) {
      $scope.topicIds.push(message.topic.id);
      $scope.topics.push(message.topic);
    });

    // when removedTopic event is fired
    $rootScope.$on("removedTopic", function (event, message) {
      $scope.topicIds = $scope.topicIds.filter(function(topicId){
        return topicId != message.identifier;
      });
      $scope.topics = $scope.topics.filter(function(topic){
        return topic.id != message.identifier;
      });
    });

    //when renamedTopic event is fired
    $rootScope.$on("renamedTopic", function (event, message) {
      $scope.topics = $scope.topics.filter(function(topic){
        return topic.id != message.identifier;
      });
      $scope.topics.push(message.topic);
    });

    $rootScope.$on("showSearchResults", function (event, message) {
        $scope.activeView = "searchResults";
    });

    $rootScope.$on("clickFeed", function (event, message) {
        $scope.activeView = "feedResults";
    });

    $rootScope.$on("clickSettings", function (event, message) {
        $scope.activeView = "settingsGroups";
    });
    // End Event handlers

    // Attributes
    $scope.expandedIndex = -1;
    $scope.predicate = "";
    $scope.activeView = "feedResults"
    // End Attributes

    // Methods
    $scope.showPopup = function() {
      $("#popupWrapper").show();
      $("#dimmer").show();
    };

    $scope.hidePopup = function() {
      $("#popupWrapper").hide();
      $("#dimmer").hide();
    };

    $scope.toggleEdit = function(topicID) {
      $(".editTopic"+topicID).show();
      $(".editBtn"+topicID).hide();
    };

    $scope.addTopic = function(topicName) {
      APIService.addTopic(topicName).success(function(data) {
        $rootScope.$broadcast("addedTopic", {
          topic: data,
        });
        $scope.hidePopup();
        $("#popupTopic input").val('');
      }).error(function(data, status, headers, config){
        console.log(status);
      });
    };

    $scope.renameTopic = function(newTopicName, topicID) {
      APIService.renameTopic(newTopicName, topicID).success(function(data) {
          $rootScope.$broadcast("renamedTopic", {
            topic: data,
            identifier: topicID,
          });
        }).error(function(data, status, headers, config){
          console.log(status);
        });
    };

    $scope.removeTopic = function(topicID) {
      APIService.removeTopic(topicID).success(function(data) {
          $rootScope.$broadcast("removedTopic", {
                identifier: topicID,
          });
        }).error(function(data, status, headers, config){
          console.log(status);
        });
    };
    $scope.fetchTopics = function() {
      // Chicken and Egg problem, the UserController may not load before this class so we need to force a promise
      // Ask the UserController if it has data yet
      $scope.$parent.getTopicIds().then(function(topic_ids){
        // TODO: Compare ids to see if we need to update the topics set
        if ($scope.topicIds != topic_ids){
          $scope.topicIds = topic_ids;
          APIService.getTopicsByIds(topic_ids).then(function(topics){
            $scope.topics = topics;
          });
        }
      });
      //$timeout(function(){$scope.fetchTopics();}, $scope.refreshInterval * 1000);
    };

    $scope.expandTopic = function(index) {
      $scope.expandedIndex = index;
    };

    //End Methods
    $scope.fetchTopics();
  })

  .controller('SearchController', function($scope, $rootScope, APIService) {

    $scope.expandSettings = function() {
      $rootScope.$broadcast("clickSettings", {});
    };

    $scope.addFeed = function() { // formerly passed url as an argument
      APIService.addFeedByUrl($scope.query).success(function(data) {
          // How do we figure out where to put it if this creates a new feed?
          $rootScope.$broadcast("addedFeed", {
                feed: data,
                topicName: "Uncategorized"
          });
          if ($("#searchForm").find(".error")) {
            $("#searchForm").find(".error").remove();
          }
        }).error(function(data, status, headers, config){
          if (status == 409) {
            $("#searchForm").append("
You are already subscribed to that feed
");
          }
        });
    };

    $scope.search = function() { // formerly passed url as an argument
      APIService.search($scope.query).success(function(data) {
          $rootScope.$broadcast("showSearchResults", {
                searchResults: data,
          });
          if ($("#searchForm").find(".error")) {
            $("#searchForm").find(".error").remove();
          }
        }).error(function(data, status, headers, config){
          if (status == 409) {
            $("#searchForm").append("
Search failed. Please check your inputs or yell at Jawwad or Justyn
");
          }
        });
    };
  })
  .controller('TopicController', function($scope, $timeout, $rootScope, APIService, FeedService) {
    // Dispatch addFeed message to a Topic
    $rootScope.$on("addedFeed", function (event, message) {
        if ($scope.topic.name == message.topicName){
          $scope.addFeedToTopic(message.feed);
        }
    });

    $rootScope.$on("addedFeedObject", function (event, message) {
        if ($scope.topic.name == message.topic.name){
          //somehow refresh the topics
          $scope.topic = message.topic;
          $scope.fetchFeeds();
        }
    });

    $scope.addFeedToTopic = function(feed) {
      // Add the feed to the local side of things
      if ($.inArray( feed.id, $scope.topic["feeds"] ) == -1) {
        $scope.topic["feeds"].push(feed.id);
        $scope.feeds.push(feed);
      } else {
        $("#searchForm").append("
You are already subscribed to that feed
");
      }
    };
    $scope.removeFeedFromTopic = function(feedId){
      // Remove Feed-Topic relationship from server
      $scope.topic["feeds"] = $scope.topic["feeds"].filter(function(id){
        return id != feedId;
      });
      APIService.updateTopic($scope.topic).success(function(data) {
        $scope.feeds = $scope.feeds.filter(function(feed) {
          return feed["id"] != feedId;
        });
      }).error(function(data, status, headers, config){
          // Log the error
          console.log(status);
          // Add the feed back since there was an error
          $scope.topic["feeds"].push(feedId);
      });
    };
    $scope.refreshTopic = function(){
      $scope.topic = $scope.$parent.topics[$scope.$parent.$index];
      //$timeout(function(){$scope.refreshTopic();}, $scope.refreshInterval * 1000);
    }
    $scope.fetchFeeds = function() {
      // Get the feed IDs
      var feed_ids = $scope.topic["feeds"];
      APIService.getFeedsByIds(feed_ids).then(function(data){
        $scope.feeds = data;
      });
    };
    //this just updates the feedService which the feedController pulls from
    $scope.expandFeed = function(feedID) {
      $rootScope.$broadcast("clickFeed", {
            identifier: feedID
        });
    };
    $scope.refreshTopic();
    $scope.fetchFeeds();
  })
  .controller('FeedController', function($scope, $rootScope,FeedService, APIService) { //scope is an angular template, from base.html, index.html
    $scope.expandedPostIndex = -1;

    $rootScope.$on("clickFeed", function (event, message) {
        $scope.feedID = message.identifier;
        $scope.fetchPosts();
        $scope.expandedPostIndex = -1;
    });

    $scope.fetchPosts = function() {
      APIService.fetchPosts($scope.feedID).success(function(data) {

        // This for loop removes unnecessary line breaks
        // TESTED WITH NYT US FEED
        // TODO: TEST THIS WITH OTHER FEEDS
        for(var i=0; i<data.length; i++){
          //create dummy div
          var tmp = document.createElement('div');

          // console.log(data[i])

          // Populate dummy div with post content
          $(tmp).html(data[i].content);

          // Get list of line breaks
          var breakList = $(tmp).find("br");

          // If more than 5 line breaks
          if (breakList.length >= 5) {
            //remove all of them
            $(tmp).find("br").remove();
          }
          // Put cleaned post content back into data array
          data[i].content = $(tmp).html();
        }
        $scope.posts = data;
      });
    };
    $scope.expandPost = function(index) {
      // Expand the post
      $scope.expandedPostIndex = index;
    };
  })
  .controller('ResultsController', function($scope, $rootScope,FeedService, APIService) { //scope is an angular template, from base.html, index.html
    $scope.searchResults = [];
    $scope.numResults = 0;
    $scope.topics = [];
    $rootScope.$on("showSearchResults", function (event, message) {
        $scope.searchResults = message.searchResults;
        $scope.numResults = message.searchResults.length;
    });

    $scope.showTopicOptions = function(feedID) {
      $scope.topics = $scope.$parent.topics;
      $scope.showPopup(feedID);
    };

    $scope.showPopup = function(feedID) {
      $(".feedID").attr("value", feedID);
      $("#popupWrapperResults").show();
      $("#dimmer").show();
    };

    $scope.hidePopup = function() {
      $("#popupWrapperResults").hide();
      $("#dimmer").hide();
    };

    $scope.addFeedObject = function() { // formerly passed url as an argument
      var feedID = parseInt($(".feedID").attr("value"));
      var topic = $.parseJSON($('input[name=selectedTopic]:checked', '#topicsForm').val());
      topic.feeds.push(feedID)
      APIService.updateTopic(topic).success(function(data) {
          $rootScope.$broadcast("addedFeedObject", {
              topic: data,
          });
          if ($("#searchForm").find(".error")) {
            $("#searchForm").find(".error").remove();
          }
          $scope.hidePopup();
          $("#topicsForm")[0].reset();
        }).error(function(data, status, headers, config){
          //if user already subscribed
          if (status == 409) {
            $("#searchForm").append("
You are already subscribed to that feed
");
          }
          console.log("fail");
        });
    };

    $scope.expandedSettingIndex = -1;
    $rootScope.$on("clickSettings", function (event, message) {
            $scope.expandedPostIndex = -1;
        });

      $scope.expandSettingsUser = function() {
      // Expand the post
      $scope.expandedSettingIndex = 1;
    };

      $scope.expandSettingsFeed = function() {
        $scope.expandedSettingIndex = 2;
      };

      $scope.expandSettingsReading = function() {
        $scope.expandedSettingIndex = 3;
      };
  });

//*/
<commit_msg>Changed location of error message<commit_after>'use strict';

/* Controllers */

angular.module('main.controllers', ['main.services'])
  .controller('UserController', function($scope, $rootScope, $timeout, $q, APIService) {
    $scope.refreshInterval = 5;
    $scope.refreshUser = function(){
      // Return a function that will keep refreshing the feeds
      var promise = APIService.getUser().then(function(user){
        $scope.user = user;
      });
      //$timeout(function(){$scope.refreshUser();}, $scope.refreshInterval * 1000);
      // I have no idea where this returns to when the function calls itself, and what
      // Angular does to garbage collect. But it works.
      return promise;
    };
    $scope.getTopicIds = function(){
      if (this.user == null){
        // Force a refresh
        var promise = $scope.refreshUser().then(function(){
          return $scope.user["topics"];
        });
        return promise;
      }
      else{
        // Return a promise that we can resolve immediately
        var deferred = $q.defer();
        deferred.resolve($scope.user["topics"]);
        return deferred.promise;
      }
    };
  })
  .controller('NavigationController', function($scope, $rootScope, $timeout, APIService) {
    $scope.topics = [];
    $scope.topicIds = [];

    // Event handlers

    // when addedTopic event is fired
    $rootScope.$on("addedTopic", function (event, message) {
      $scope.topicIds.push(message.topic.id);
      $scope.topics.push(message.topic);
    });

    // when removedTopic event is fired
    $rootScope.$on("removedTopic", function (event, message) {
      $scope.topicIds = $scope.topicIds.filter(function(topicId){
        return topicId != message.identifier;
      });
      $scope.topics = $scope.topics.filter(function(topic){
        return topic.id != message.identifier;
      });
    });

    //when renamedTopic event is fired
    $rootScope.$on("renamedTopic", function (event, message) {
      $scope.topics = $scope.topics.filter(function(topic){
        return topic.id != message.identifier;
      });
      $scope.topics.push(message.topic);
    });

    $rootScope.$on("showSearchResults", function (event, message) {
        $scope.activeView = "searchResults";
    });

    $rootScope.$on("clickFeed", function (event, message) {
        $scope.activeView = "feedResults";
    });

    $rootScope.$on("clickSettings", function (event, message) {
        $scope.activeView = "settingsGroups";
    });
    // End Event handlers

    // Attributes
    $scope.expandedIndex = -1;
    $scope.predicate = "";
    $scope.activeView = "feedResults"
    // End Attributes

    // Methods
    $scope.showPopup = function() {
      $("#popupWrapper").show();
      $("#dimmer").show();
    };

    $scope.hidePopup = function() {
      $("#popupWrapper").hide();
      $("#dimmer").hide();
    };

    $scope.toggleEdit = function(topicID) {
      $(".editTopic"+topicID).show();
      $(".editBtn"+topicID).hide();
    };

    $scope.addTopic = function(topicName) {
      APIService.addTopic(topicName).success(function(data) {
        $rootScope.$broadcast("addedTopic", {
          topic: data,
        });
        $scope.hidePopup();
        $("#popupTopic input").val('');
      }).error(function(data, status, headers, config){
        console.log(status);
      });
    };

    $scope.renameTopic = function(newTopicName, topicID) {
      APIService.renameTopic(newTopicName, topicID).success(function(data) {
          $rootScope.$broadcast("renamedTopic", {
            topic: data,
            identifier: topicID,
          });
        }).error(function(data, status, headers, config){
          console.log(status);
        });
    };

    $scope.removeTopic = function(topicID) {
      APIService.removeTopic(topicID).success(function(data) {
          $rootScope.$broadcast("removedTopic", {
                identifier: topicID,
          });
        }).error(function(data, status, headers, config){
          console.log(status);
        });
    };
    $scope.fetchTopics = function() {
      // Chicken and Egg problem, the UserController may not load before this class so we need to force a promise
      // Ask the UserController if it has data yet
      $scope.$parent.getTopicIds().then(function(topic_ids){
        // TODO: Compare ids to see if we need to update the topics set
        if ($scope.topicIds != topic_ids){
          $scope.topicIds = topic_ids;
          APIService.getTopicsByIds(topic_ids).then(function(topics){
            $scope.topics = topics;
          });
        }
      });
      //$timeout(function(){$scope.fetchTopics();}, $scope.refreshInterval * 1000);
    };

    $scope.expandTopic = function(index) {
      $scope.expandedIndex = index;
    };

    //End Methods
    $scope.fetchTopics();
  })

  .controller('SearchController', function($scope, $rootScope, APIService) {

    $scope.expandSettings = function() {
      $rootScope.$broadcast("clickSettings", {});
    };

    $scope.addFeed = function() { // formerly passed url as an argument
      APIService.addFeedByUrl($scope.query).success(function(data) {
          // How do we figure out where to put it if this creates a new feed?
          $rootScope.$broadcast("addedFeed", {
                feed: data,
                topicName: "Uncategorized"
          });
          if ($("#searchForm").find(".error")) {
            $("#searchForm").find(".error").remove();
          }
        }).error(function(data, status, headers, config){
          if (status == 409) {
            console.log("made it here")
            $("#searchForm").append("
You are already subscribed to that feed
");
          }
        });
    };

    $scope.search = function() { // formerly passed url as an argument
      APIService.search($scope.query).success(function(data) {
          $rootScope.$broadcast("showSearchResults", {
                searchResults: data,
          });
          if ($("#searchForm").find(".error")) {
            $("#searchForm").find(".error").remove();
          }
        }).error(function(data, status, headers, config){
          if (status == 409) {
            $("#searchForm").append("
Search failed. Please check your inputs or yell at Jawwad or Justyn
");
          }
        });
    };
  })
  .controller('TopicController', function($scope, $timeout, $rootScope, APIService, FeedService) {
    // Dispatch addFeed message to a Topic
    $rootScope.$on("addedFeed", function (event, message) {
        if ($scope.topic.name == message.topicName){
          $scope.addFeedToTopic(message.feed);
        }
    });

    $rootScope.$on("addedFeedObject", function (event, message) {
        if ($scope.topic.name == message.topic.name){
          //somehow refresh the topics
          $scope.topic = message.topic;
          $scope.fetchFeeds();
        }
    });

    $scope.addFeedToTopic = function(feed) {
      // Add the feed to the local side of things
      if ($.inArray( feed.id, $scope.topic["feeds"] ) == -1) {
        $scope.topic["feeds"].push(feed.id);
        $scope.feeds.push(feed);
      } else {
        $("#searchForm").append("
You are already subscribed to that feed
");
      }
    };
    $scope.removeFeedFromTopic = function(feedId){
      // Remove Feed-Topic relationship from server
      $scope.topic["feeds"] = $scope.topic["feeds"].filter(function(id){
        return id != feedId;
      });
      APIService.updateTopic($scope.topic).success(function(data) {
        $scope.feeds = $scope.feeds.filter(function(feed) {
          return feed["id"] != feedId;
        });
      }).error(function(data, status, headers, config){
          // Log the error
          console.log(status);
          // Add the feed back since there was an error
          $scope.topic["feeds"].push(feedId);
      });
    };
    $scope.refreshTopic = function(){
      $scope.topic = $scope.$parent.topics[$scope.$parent.$index];
      //$timeout(function(){$scope.refreshTopic();}, $scope.refreshInterval * 1000);
    }
    $scope.fetchFeeds = function() {
      // Get the feed IDs
      var feed_ids = $scope.topic["feeds"];
      APIService.getFeedsByIds(feed_ids).then(function(data){
        $scope.feeds = data;
      });
    };
    //this just updates the feedService which the feedController pulls from
    $scope.expandFeed = function(feedID) {
      $rootScope.$broadcast("clickFeed", {
            identifier: feedID
        });
    };
    $scope.refreshTopic();
    $scope.fetchFeeds();
  })
  .controller('FeedController', function($scope, $rootScope,FeedService, APIService) { //scope is an angular template, from base.html, index.html
    $scope.expandedPostIndex = -1;

    $rootScope.$on("clickFeed", function (event, message) {
        $scope.feedID = message.identifier;
        $scope.fetchPosts();
        $scope.expandedPostIndex = -1;
    });

    $scope.fetchPosts = function() {
      APIService.fetchPosts($scope.feedID).success(function(data) {

        // This for loop removes unnecessary line breaks
        // TESTED WITH NYT US FEED
        // TODO: TEST THIS WITH OTHER FEEDS
        for(var i=0; i<data.length; i++){
          //create dummy div
          var tmp = document.createElement('div');

          // console.log(data[i])

          // Populate dummy div with post content
          $(tmp).html(data[i].content);

          // Get list of line breaks
          var breakList = $(tmp).find("br");

          // If more than 5 line breaks
          if (breakList.length >= 5) {
            //remove all of them
            $(tmp).find("br").remove();
          }
          // Put cleaned post content back into data array
          data[i].content = $(tmp).html();
        }
        $scope.posts = data;
      });
    };
    $scope.expandPost = function(index) {
      // Expand the post
      $scope.expandedPostIndex = index;
    };
  })
  .controller('ResultsController', function($scope, $rootScope,FeedService, APIService) { //scope is an angular template, from base.html, index.html
    $scope.searchResults = [];
    $scope.numResults = 0;
    $scope.topics = [];
    $rootScope.$on("showSearchResults", function (event, message) {
        $scope.searchResults = message.searchResults;
        $scope.numResults = message.searchResults.length;
    });

    $scope.showTopicOptions = function(feedID) {
      $scope.topics = $scope.$parent.topics;
      $scope.showPopup(feedID);
    };

    $scope.showPopup = function(feedID) {
      $(".feedID").attr("value", feedID);
      $("#popupWrapperResults").show();
      $("#dimmer").show();
    };

    $scope.hidePopup = function() {
      $("#popupWrapperResults").hide();
      $("#dimmer").hide();
    };

    $scope.addFeedObject = function() { // formerly passed url as an argument
      var feedID = parseInt($(".feedID").attr("value"));
      var topic = $.parseJSON($('input[name=selectedTopic]:checked', '#topicsForm').val());
      topic.feeds.push(feedID)
      APIService.updateTopic(topic).success(function(data) {
          $rootScope.$broadcast("addedFeedObject", {
              topic: data,
          });
          if ($("#searchForm").find(".error")) {
            $("#searchForm").find(".error").remove();
          }
          $scope.hidePopup();
          $("#topicsForm")[0].reset();
        }).error(function(data, status, headers, config){
          //if user already subscribed
          if (status == 409) {
            $("#topicsForm").append("
You are already subscribed to that feed
");
          }
        });
    };

    $scope.expandedSettingIndex = -1;
    $rootScope.$on("clickSettings", function (event, message) {
            $scope.expandedPostIndex = -1;
        });

      $scope.expandSettingsUser = function() {
      // Expand the post
      $scope.expandedSettingIndex = 1;
    };

      $scope.expandSettingsFeed = function() {
        $scope.expandedSettingIndex = 2;
      };

      $scope.expandSettingsReading = function() {
        $scope.expandedSettingIndex = 3;
      };
  });

//*/
<|endoftext|>


<commit_before>import React from 'react';
import { mount, render } from 'enzyme';
import { expect } from 'chai';
import Immutable from 'immutable';

// see: https://github.com/mochajs/mocha/issues/1847
const { describe, it } = global;

import Visualizer from '../Visualizer';
import { defaultLabels } from '../../defaults';

describe('<Visualizer />', () => {

  const sequence = new Immutable.List('ATTTGCGTCG'.split(''));
  let context;

  before(() => {
    context = {
      controller: {
        on: () => {},
        dispatch: () => {},
      }
    };
  });

  it('renders a SVG element with appropriate dimensions', () => {
    const childContextTypes = { controller: React.PropTypes.object.isRequired };
    const wrapper = mount(
      <Visualizer
        sequence={sequence}
        labels={defaultLabels}
        positionFrom={0}
      />,
      { context, childContextTypes }
    );

    expect(wrapper.find(Visualizer)).to.have.length(1);
    expect(wrapper.ref('wrapper')).to.have.length(1);
    expect(wrapper.find('svg')).to.have.length(1);
    expect(wrapper.instance().state.width).to.equal('100%');
    expect(wrapper.instance().state.height).to.equal('100%');
  });
});
<commit_msg>Add a few more tests for the Visualizer<commit_after>import React from 'react';
import { shallow, mount } from 'enzyme';
import { expect } from 'chai';
import Immutable from 'immutable';
import sinon from 'sinon';

// see: https://github.com/mochajs/mocha/issues/1847
const { describe, it } = global;

import Visualizer from '../Visualizer';
import { defaultLabels } from '../../defaults';

describe('<Visualizer />', () => {

  const sequence = new Immutable.List('ATTTGCGTCG'.split(''));

  const childContextTypes = { controller: React.PropTypes.object.isRequired };
  let context;

  before(() => {
    context = {
      controller: {
        on: () => {},
        dispatch: () => {},
      }
    };
  });

  it('renders a SVG element with appropriate dimensions', () => {
    const wrapper = mount(
      <Visualizer
        sequence={sequence}
        labels={defaultLabels}
        positionFrom={0}
      />,
      { context, childContextTypes }
    );

    expect(wrapper.find(Visualizer)).to.have.length(1);
    expect(wrapper.ref('wrapper')).to.have.length(1);
    expect(wrapper.find('svg')).to.have.length(1);
    expect(wrapper.instance().state.width).to.equal('100%');
    expect(wrapper.instance().state.height).to.equal('100%');
  });

  it('renders help panel if sequence is empty', () => {
    const wrapper = shallow(
      <Visualizer
        sequence={new Immutable.List()}
        labels={defaultLabels}
        positionFrom={0}
      />
    );

    expect(wrapper.find('.help')).to.have.length(1);
    expect(wrapper.find('svg')).to.have.length(0);
  });

  it('adds a listener to window resize', () => {
    window.addEventListener = sinon.spy();

    const wrapper = mount(
      <Visualizer
        sequence={sequence}
        labels={defaultLabels}
        positionFrom={0}
      />,
      { context, childContextTypes }
    );

    expect(window.addEventListener.calledWith('resize')).to.be.true;
  });

  it('updates dimensions when receiving new props', () => {
    const wrapper = mount(
      <Visualizer
        sequence={sequence}
        labels={defaultLabels}
        positionFrom={0}
      />,
      { context, childContextTypes }
    );

    expect(wrapper.state('nucleotidesPerRow')).to.equal(80);

    // test starts here
    wrapper.setProps({
      labels: defaultLabels,
      sequence: new Immutable.List(),
    });

    // Well... it works but we cannot assert something else since
    // it is not possible to get a valid value for `clientWidth` in
    // the method `updateVisualizerDimensions` of the component
    expect(wrapper.state('nucleotidesPerRow')).to.not.equal(80);
  });
});
<|endoftext|>


<commit_before>/**
 * Express configuration
 */
'use strict';

var compress = require('compression');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var errorHandler = require('errorhandler');
var session = require('express-session');
var logger = require('morgan');<% if (dbOption === 'MongoDB') { %>
var MongoStore = require('connect-mongo')({
    session: session
});<% } %><% if ('MySQL'.indexOf(dbOption) > -1) { %>
var SequelizeStore = require('connect-session-sequelize')(session.Store);<% } %>

// Configuration files
var secrets = require('./secrets');
var settings = require('./settings');
var security = require('./security');

module.exports = function(app, express,<% if ('MySQL'.indexOf(dbOption) > -1) { %> sequelize,<% } %> path) {

    var hour = 3600000;
    var day = hour * 24;
    var week = day * 7;

    var env = app.get('env');

    // Setup port for server to run on
    app.set('port', settings.server.port);

     // Setup view engine for server side templating<% if (structure === 'Single Page Application' || htmlOption === 'None (Vanilla HTML)') { %>
    app.engine('.html', require('ejs').__express);
    app.set('view engine', 'html');<% } %><% if (structure === 'Static Site' && htmlOption !== 'None (Vanilla HTML)') { %>
    app.engine('<%= htmlOption === 'Jade' ? 'jade' : '' %><%= htmlOption === 'Swig' ? 'swig' : '' %><%= htmlOption === 'None (Vanilla HTML)' ? 'html' : '' %>', require('<%= htmlOption.toLowerCase() %>').renderFile);
    app.set('view engine', '<%= htmlOption === 'Jade' ? 'jade' : '' %><%= htmlOption === 'Swig' ? 'swig' : '' %>

    // Remove x-powered-by header (doesn't let clients know we are using Express)
    app.disable('x-powered-by');

    if ('development' === env) {
        app.use(require('connect-livereload')());

        // Setup log level for server console output
        app.use(logger('dev'));

        // Disable caching of scripts for easier testing
        app.use(function noCache(req, res, next) {
            if (req.url.indexOf('/scripts/') === 0) {
                res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
                res.header('Pragma', 'no-cache');
                res.header('Expires', 0);
            }
            next();
        });

        app.use(express.static(path.join(settings.root, settings.staticAssets), {maxAge: week}));
    }

    if ('production' === env) {
        app.use(compress());
        // Mount public/ folder for static assets and set cache via maxAge
        app.use(express.static(path.join(settings.root, settings.staticAssets), {
            maxAge: week
        }));
    }

    // Setup path where all server templates will reside<% if (structure === 'Single Page Application') { %>
    app.set('views', path.join(settings.root, 'lib/views'));<% } %><% if (structure === 'Static Site') { %>
    app.set('views', path.join(settings.root, 'dev/templates'));
    <% } %>

    // Returns middleware that parses both json and urlencoded.
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

    // Parse Cookie header and populate req.cookies with an object keyed by the cookie names
    app.use(cookieParser(secrets.cookieSecret));

    app.use(session({
        secret: secrets.sessionSecret,
        saveUninitialized: true,
        resave: true,<% if (dbOption === 'MongoDB') { %>
        store: new MongoStore({
            url: settings.database.url,
            auto_reconnect: true,
        }),<% } %><% if (dbOption === 'MySQL') { %>
        store: new SequelizeStore({
            db: sequelize
        }),<% } %>
        cookie: {
            httpOnly: true, /*, secure: true for HTTPS*/
            maxAge: day
        }
    }));

    // Initialize Lusca Security
    app.use(function(req, res, next) {
        security(req, res, next);
    });

    app.use(function(req, res, next) {
        res.locals.user = req.user;
        next();
    });

    // Load all routes
    require('fs').readdirSync(path.join(settings.root, './lib/routes/')).forEach(function(file) {
        require(path.join(settings.root, './lib/routes/') + file)(app);
    });

    /**
     * 500 Error Handler.
     * As of Express 4.0 it must be placed at the end of all routes.
     */
    app.use(errorHandler());

};<commit_msg>Fixed templating issue in express.js<commit_after>/**
 * Express configuration
 */
'use strict';

var compress = require('compression');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var errorHandler = require('errorhandler');
var session = require('express-session');
var logger = require('morgan');<% if (dbOption === 'MongoDB') { %>
var MongoStore = require('connect-mongo')({
    session: session
});<% } %><% if ('MySQL'.indexOf(dbOption) > -1) { %>
var SequelizeStore = require('connect-session-sequelize')(session.Store);<% } %>

// Configuration files
var secrets = require('./secrets');
var settings = require('./settings');
var security = require('./security');

module.exports = function(app, express,<% if ('MySQL'.indexOf(dbOption) > -1) { %> sequelize,<% } %> path) {

    var hour = 3600000;
    var day = hour * 24;
    var week = day * 7;

    var env = app.get('env');

    // Setup port for server to run on
    app.set('port', settings.server.port);

     // Setup view engine for server side templating<% if (structure === 'Single Page Application' || htmlOption === 'None (Vanilla HTML)') { %>
    app.engine('.html', require('ejs').__express);
    app.set('view engine', 'html');<% } %><% if (structure === 'Static Site' && htmlOption !== 'None (Vanilla HTML)') { %>
    app.engine('<%= htmlOption === 'Jade' ? 'jade' : '' %><%= htmlOption === 'Swig' ? 'swig' : '' %><%= htmlOption === 'None (Vanilla HTML)' ? 'html' : '' %>', require('<%= htmlOption.toLowerCase() %>').renderFile);
    app.set('view engine', '<%= htmlOption === 'Jade' ? 'jade' : '' %><%= htmlOption === 'Swig' ? 'swig' : '' %>');<% } %>

    // Remove x-powered-by header (doesn't let clients know we are using Express)
    app.disable('x-powered-by');

    if ('development' === env) {
        app.use(require('connect-livereload')());

        // Setup log level for server console output
        app.use(logger('dev'));

        // Disable caching of scripts for easier testing
        app.use(function noCache(req, res, next) {
            if (req.url.indexOf('/scripts/') === 0) {
                res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
                res.header('Pragma', 'no-cache');
                res.header('Expires', 0);
            }
            next();
        });

        app.use(express.static(path.join(settings.root, settings.staticAssets), {maxAge: week}));
    }

    if ('production' === env) {
        app.use(compress());
        // Mount public/ folder for static assets and set cache via maxAge
        app.use(express.static(path.join(settings.root, settings.staticAssets), {
            maxAge: week
        }));
    }

    // Setup path where all server templates will reside<% if (structure === 'Single Page Application') { %>
    app.set('views', path.join(settings.root, 'lib/views'));<% } %><% if (structure === 'Static Site') { %>
    app.set('views', path.join(settings.root, 'dev/templates'));
    <% } %>

    // Returns middleware that parses both json and urlencoded.
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));

    // Parse Cookie header and populate req.cookies with an object keyed by the cookie names
    app.use(cookieParser(secrets.cookieSecret));

    app.use(session({
        secret: secrets.sessionSecret,
        saveUninitialized: true,
        resave: true,<% if (dbOption === 'MongoDB') { %>
        store: new MongoStore({
            url: settings.database.url,
            auto_reconnect: true,
        }),<% } %><% if (dbOption === 'MySQL') { %>
        store: new SequelizeStore({
            db: sequelize
        }),<% } %>
        cookie: {
            httpOnly: true, /*, secure: true for HTTPS*/
            maxAge: day
        }
    }));

    // Initialize Lusca Security
    app.use(function(req, res, next) {
        security(req, res, next);
    });

    app.use(function(req, res, next) {
        res.locals.user = req.user;
        next();
    });

    // Load all routes
    require('fs').readdirSync(path.join(settings.root, './lib/routes/')).forEach(function(file) {
        require(path.join(settings.root, './lib/routes/') + file)(app);
    });

    /**
     * 500 Error Handler.
     * As of Express 4.0 it must be placed at the end of all routes.
     */
    app.use(errorHandler());

};<|endoftext|>


<commit_before>/**
 * TagSpaces - universal file and folder organizer
 * Copyright (C) 2017-present TagSpaces UG (haftungsbeschraenkt)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License (version 3) as
 * published by the Free Software Foundation.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * @flow
 */
<commit_msg>removing unneeded file<commit_after><|endoftext|>


<commit_before>function statistics(state = window.caseData.statistics = {}, action) {
  return state
}

export default statistics
<commit_msg>Restore statistics visiblity<commit_after>function statistics(state = window.caseData.statistics || {}, action) {
  return state
}

export default statistics
<|endoftext|>