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

/**
 * @fileoverview Controller for the exploration editor feedback tab.
 *
 * @author <EMAIL> (<NAME>)
 */

oppia.controller('FeedbackTab', [
  '$scope', '$http', '$modal', '$timeout', '$rootScope', 'warningsData',
  'oppiaDatetimeFormatter', 'threadStatusDisplayService',
  'threadDataService', 'explorationStatesService', 'explorationData',
  'changeListService',
  function(
    $scope, $http, $modal, $timeout, $rootScope, warningsData,
    oppiaDatetimeFormatter, threadStatusDisplayService,
    threadDataService, explorationStatesService, explorationData,
    changeListService) {
    var ACTION_ACCEPT_SUGGESTION = 'accept';
    var ACTION_REJECT_SUGGESTION = 'reject';
    $scope.STATUS_CHOICES = threadStatusDisplayService.STATUS_CHOICES;
    $scope.threadData = threadDataService.data;
    $scope.getLabelClass = threadStatusDisplayService.getLabelClass;
    $scope.getHumanReadableStatus = (
      threadStatusDisplayService.getHumanReadableStatus);
    $scope.getLocaleAbbreviatedDatetimeString = (
      oppiaDatetimeFormatter.getLocaleAbbreviatedDatetimeString);

    $scope.activeThread = null;
    $rootScope.loadingMessage = 'Loading';
    $scope.tmpMessage = {
      status: null,
      text: ''
    };

    var _resetTmpMessageFields = function() {
      $scope.tmpMessage.status = $scope.activeThread ?
        $scope.activeThread.status : null;
      $scope.tmpMessage.text = '';
    };

    $scope.clearActiveThread = function() {
      $scope.activeThread = null;
      _resetTmpMessageFields();
    };

    $scope.showCreateThreadModal = function() {
      $modal.open({
        templateUrl: 'modals/editorFeedbackCreateThread',
        backdrop: true,
        resolve: {},
        controller: ['$scope', '$modalInstance', function(
          $scope, $modalInstance) {
          $scope.newThreadSubject = '';
          $scope.newThreadText = '';

          $scope.create = function(newThreadSubject, newThreadText) {
            if (!newThreadSubject) {
              warningsData.addWarning('Please specify a thread subject.');
              return;
            }
            if (!newThreadText) {
              warningsData.addWarning('Please specify a message.');
              return;
            }

            $modalInstance.close({
              newThreadSubject: newThreadSubject,
              newThreadText: newThreadText
            });
          };

          $scope.cancel = function() {
            $modalInstance.dismiss('cancel');
          };
        }]
      }).result.then(function(result) {
        threadDataService.createNewThread(
          result.newThreadSubject, result.newThreadText, function() {
            $scope.clearActiveThread();
          });
      });
    };

    $scope.isSuggestionValid = function() {
      var activeThread = $scope.activeThread;
      var currentStatus = activeThread.status;
      var suggestionExpVersion = activeThread.suggestion.exploration_version;
      return ($scope.activeThread.status === 'open' &&
              explorationData.data.version === suggestionExpVersion);
    };

    $scope.hasUnsavedChanges = function() {
      return (changeListService.getChangeList().length > 0);
    };

    $scope.viewSuggestionBtnType = function() {
      return ($scope.isSuggestionValid() && !$scope.hasUnsavedChanges() ?
              'primary' : 'default');
    };

    // TODO(Allan): Implement ability to edit suggestions before applying.
    $scope.showSuggestionModal = function() {
      $modal.open({
        templateUrl: 'modals/editorViewSuggestion',
        backdrop: true,
        size: 'lg',
        resolve: {
          suggestionInfo: function() {
            return {
              isSuggestionValid: $scope.isSuggestionValid(),
              hasUnsavedChanges: $scope.hasUnsavedChanges()
            };
          },
          stateContent: function() {
            var states = explorationData.data.states;
            var stateName = $scope.activeThread.suggestion.state_name;
            return {
              oldContent: states[stateName].content[0].value,
              newContent: $scope.activeThread.suggestion.state_content.value
            };
          }
        },
        controller: [
          '$scope', '$modalInstance', 'suggestionInfo', 'stateContent',
          function($scope, $modalInstance, suggestionInfo, stateContent) {
          var ACTION_INVALID_MSG = 'This suggestion has already been ' +
            'acted upon, or was made for an outdated version ' +
            'of this exploration.';
          var UNSAVED_CHANGES_MSG = 'You have unsaved changes to this ' +
            'exploration. Please save your changes before acting on ' +
            'a suggestion.';
          $scope.canActOnSuggestion = suggestionInfo.isSuggestionValid &&
            !suggestionInfo.hasUnsavedChanges;
          $scope.errorMessage = suggestionInfo.isSuggestionValid ?
            UNSAVED_CHANGES_MSG : ACTION_INVALID_MSG;
          $scope.oldContent = stateContent.oldContent;
          $scope.newContent = stateContent.newContent;
          $scope.commitMessage = '';

          $scope.acceptSuggestion = function() {
            $modalInstance.close({
              action: ACTION_ACCEPT_SUGGESTION,
              commitMsg: $scope.commitMessage
            });
          };

          $scope.rejectSuggestion = function() {
            $modalInstance.close({
              action: ACTION_REJECT_SUGGESTION
            });
          };

          $scope.cancelReview = function() {
            $modalInstance.dismiss();
          };
        }]
      }).result.then(function(result) {
        threadDataService.resolveSuggestion(
          $scope.activeThread.thread_id, result.action, result.commitMsg,
          function() {
            threadDataService.fetchThreads(function() {
              $scope.setActiveThread($scope.activeThread.thread_id);
            });
            // Immediately update editor to reflect accepted suggestion.
            if (result.action === ACTION_ACCEPT_SUGGESTION) {
              var suggestion = $scope.activeThread.suggestion;
              var stateName = suggestion.state_name;
              var state = explorationData.data.states[stateName];
              state.content[0].value = suggestion.state_content.value;
              explorationData.data.version += 1;
              explorationStatesService.setState(stateName, state);
              $rootScope.$broadcast('refreshStateEditor');
            }
          }, function() {
            console.log('Error resolving suggestion');
          });
      });
    };
<commit_msg>Simplify editor suggestion modal resolve<commit_after>// Copyright 2014 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Controller for the exploration editor feedback tab.
 *
 * @author <EMAIL> (<NAME>)
 */

oppia.controller('FeedbackTab', [
  '$scope', '$http', '$modal', '$timeout', '$rootScope', 'warningsData',
  'oppiaDatetimeFormatter', 'threadStatusDisplayService',
  'threadDataService', 'explorationStatesService', 'explorationData',
  'changeListService',
  function(
    $scope, $http, $modal, $timeout, $rootScope, warningsData,
    oppiaDatetimeFormatter, threadStatusDisplayService,
    threadDataService, explorationStatesService, explorationData,
    changeListService) {
    var ACTION_ACCEPT_SUGGESTION = 'accept';
    var ACTION_REJECT_SUGGESTION = 'reject';
    $scope.STATUS_CHOICES = threadStatusDisplayService.STATUS_CHOICES;
    $scope.threadData = threadDataService.data;
    $scope.getLabelClass = threadStatusDisplayService.getLabelClass;
    $scope.getHumanReadableStatus = (
      threadStatusDisplayService.getHumanReadableStatus);
    $scope.getLocaleAbbreviatedDatetimeString = (
      oppiaDatetimeFormatter.getLocaleAbbreviatedDatetimeString);

    $scope.activeThread = null;
    $rootScope.loadingMessage = 'Loading';
    $scope.tmpMessage = {
      status: null,
      text: ''
    };

    var _resetTmpMessageFields = function() {
      $scope.tmpMessage.status = $scope.activeThread ?
        $scope.activeThread.status : null;
      $scope.tmpMessage.text = '';
    };

    $scope.clearActiveThread = function() {
      $scope.activeThread = null;
      _resetTmpMessageFields();
    };

    $scope.showCreateThreadModal = function() {
      $modal.open({
        templateUrl: 'modals/editorFeedbackCreateThread',
        backdrop: true,
        resolve: {},
        controller: ['$scope', '$modalInstance', function(
          $scope, $modalInstance) {
          $scope.newThreadSubject = '';
          $scope.newThreadText = '';

          $scope.create = function(newThreadSubject, newThreadText) {
            if (!newThreadSubject) {
              warningsData.addWarning('Please specify a thread subject.');
              return;
            }
            if (!newThreadText) {
              warningsData.addWarning('Please specify a message.');
              return;
            }

            $modalInstance.close({
              newThreadSubject: newThreadSubject,
              newThreadText: newThreadText
            });
          };

          $scope.cancel = function() {
            $modalInstance.dismiss('cancel');
          };
        }]
      }).result.then(function(result) {
        threadDataService.createNewThread(
          result.newThreadSubject, result.newThreadText, function() {
            $scope.clearActiveThread();
          });
      });
    };

    $scope.isSuggestionValid = function() {
      var activeThread = $scope.activeThread;
      var currentStatus = activeThread.status;
      var suggestionExpVersion = activeThread.suggestion.exploration_version;
      return ($scope.activeThread.status === 'open' &&
              explorationData.data.version === suggestionExpVersion);
    };

    $scope.hasUnsavedChanges = function() {
      return (changeListService.getChangeList().length > 0);
    };

    $scope.viewSuggestionBtnType = function() {
      return ($scope.isSuggestionValid() && !$scope.hasUnsavedChanges() ?
              'primary' : 'default');
    };

    // TODO(Allan): Implement ability to edit suggestions before applying.
    $scope.showSuggestionModal = function() {
      $modal.open({
        templateUrl: 'modals/editorViewSuggestion',
        backdrop: true,
        size: 'lg',
        resolve: {
          isSuggestionValid: function() {
            return $scope.isSuggestionValid();
          },
          hasUnsavedChanges: function() {
            return $scope.hasUnsavedChanges();
          },
          oldContent: function() {
            var stateName = $scope.activeThread.suggestion.state_name;
            return explorationData.data.states[stateName].content[0].value;
          },
          newContent: function() {
            return $scope.activeThread.suggestion.state_content.value;
          }
        },
        controller: [
          '$scope', '$modalInstance', 'isSuggestionValid', 'hasUnsavedChanges',
          'oldContent', 'newContent',
          function(
            $scope, $modalInstance, isSuggestionValid, hasUnsavedChanges,
            oldContent, newContent) {
            var ACTION_INVALID_MSG = 'This suggestion has already been ' +
              'acted upon, or was made for an outdated version ' +
              'of this exploration.';
            var UNSAVED_CHANGES_MSG = 'You have unsaved changes to this ' +
              'exploration. Please save your changes before acting on ' +
              'a suggestion.';
            $scope.canActOnSuggestion = isSuggestionValid && !hasUnsavedChanges;
            $scope.errorMessage = isSuggestionValid ?
              UNSAVED_CHANGES_MSG : ACTION_INVALID_MSG;
            $scope.oldContent = oldContent;
            $scope.newContent = newContent;
            $scope.commitMessage = '';

            $scope.acceptSuggestion = function() {
              $modalInstance.close({
                action: ACTION_ACCEPT_SUGGESTION,
                commitMsg: $scope.commitMessage
              });
            };

            $scope.rejectSuggestion = function() {
              $modalInstance.close({
                action: ACTION_REJECT_SUGGESTION
              });
            };

            $scope.cancelReview = function() {
              $modalInstance.dismiss();
            };
          }
        ]
      }).result.then(function(result) {
        threadDataService.resolveSuggestion(
          $scope.activeThread.thread_id, result.action, result.commitMsg,
          function() {
            threadDataService.fetchThreads(function() {
              $scope.setActiveThread($scope.activeThread.thread_id);
            });
            // Immediately update editor to reflect accepted suggestion.
            if (result.action === ACTION_ACCEPT_SUGGESTION) {
              var suggestion = $scope.activeThread.suggestion;
              var stateName = suggestion.state_name;
              var state = explorationData.data.states[stateName];
              state.content[0].value = suggestion.state_content.value;
              explorationData.data.version += 1;
              explorationStatesService.setState(stateName, state);
              $rootScope.$broadcast('refreshStateEditor');
            }
          }, function() {
            console.log('Error resolving suggestion');
          });
      });
    };

{'fraction_non_alphanumeric': 0.10790870854306006, 'fraction_numerical': 0.0016548300351651383, 'mean_word_length': 2.3745928338762217, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1789147', 'n_tokens_mistral': 3788, 'n_tokens_neox': 3680, 'n_words': 778}