<commit_before>/*jslint browser: true, white: true, plusplus: true, eqeq: true, */
/*global angular, console, alert*/

(function () {
  'use strict';

  var app = angular.module('keira2');

  app.controller("SmartAIController", function ($rootScope, $scope, $http, $stateParams, $modal) {

    /* read ONLY values, do NOT bind them with ng-model in the view */
    $scope.sourceType = $stateParams.sourceType;
    $scope.entryOrGuid = $stateParams.sourceType;

    /* All SAI tabs, disabled by default.
    *  Only one tab can be active at a time */
    $scope.saiTabs = {
      search : false,
      create : false,
      editor : false,
      script : false
    };

    /* source_type constants */
    $scope.sourceTypesConst = {
      CREATURE          : 0, 0 : "Creature",
      GAMEOBJECT        : 1, 1 : "GameObject",
      AREATRIGGER       : 2, 2 : "AreaTrigger",
      EVENT             : 3, 3 : "Event",
      GOSSIP            : 4, 4 : "Gossip",
      QUEST             : 5, 5 : "Quest",
      SPELL             : 6, 6 : "Spell",
      TRANSPORT         : 7, 7 : "Transport",
      INSTANCE          : 8, 8 : "Instance",
      TIMED_ACTIONLIST  : 9, 9 : "Timed Actionlist"
    };

    /* Init arrays */
    $scope.exactResult            = [];
    $scope.search_smart_scripts   = [];
    $scope.new_smart_scripts      = [];
    $scope.current_smart_scripts  = [];

    /* Default source_type of search */
    $scope.search_smart_scripts.source_type = 0;

    /* Do not show exact result div in search by default */
    $scope.foundExactResult = false;

    /* Check if an entity (smart_scripts.source_type AND smart_scripts.entryorguid) is selected */
    if ($stateParams.sourceType && $stateParams.entryOrGuid) {

      /* We have a creature selected and default active tab is creatureTemplate */
      $scope.isEntitySelected = true;
      $scope.saiTabs.editor = true;

      /*  Following lines retrieve all SAI datas
       *  current_* mantains the database state
       *  new_*     mantains the editor state
       *  we will use those two objects to generate the SQL queries
       */

      /* Retrieve all smart_scripts datas */
      $http.get( app.api + "smart_scripts/" + $stateParams.sourceType + "/" + $stateParams.entryOrGuid )
        .success(function (data, status, header, config) {
        $scope.current_smart_scripts = $rootScope.fixNumericValues(data);
        $scope.new_smart_scripts = angular.copy($scope.current_smart_scripts);

        // check if we are editing an existing SAI script or creating a new one
        if ($scope.current_smart_scripts.length > 0) {
          // editing existing SAI script
          $scope.selectionText = "Editing the SmartAI script of ";
        } else {
          // creating new SAI script
          $scope.selectionText = "Creating a new SmartAI script for ";
        }

        $scope.selectionText += "[" +  $scope.sourceTypesConst[$stateParams.sourceType] + "] ";

        if ($stateParams.sourceType == 0 || $stateParams.sourceType == 1) {
          if ($stateParams.entryOrGuid > 0) {
            $scope.selectionText += "ENTRY ";
            $scope.selectionText += $stateParams.entryOrGuid;
          } else {
            $scope.selectionText += "GUID ";
            $scope.selectionText += -$stateParams.entryOrGuid;
          }
        } else {
          $scope.selectionText += $stateParams.entryOrGuid;
        }

        switch (Number($stateParams.sourceType)) {

          case 0: // Creature
            if ($stateParams.entryOrGuid < 0) {

              // Creature GUID
              $scope.entityGuid = -$stateParams.entryOrGuid;

              /* Retrieve creature_template.entry */
              $http.get( app.api + "creature/spawn/guid/" + $scope.entityGuid)
                .success(function (data, status, header, config) {
                if (data.length < 1) {
                  console.log("[WARNING] creature/spawn/guid/" + $scope.entityGuid + " returned 0 results: unable to find the entry of the creature.");
                } else {
                  if (!data[0].hasOwnProperty('id')) {
                    console.log("[ERROR] creature/spawn/guid/" + $scope.entityGuid + " returned datas, but the attribute 'id' is not present.");
                  } else {
                    $scope.entityEntry = data[0].id;

                    /* Retrieve all creature_template datas */
                    $http.get( app.api + "creature/template/" + $scope.entityEntry )
                      .success(function (data, status, header, config) {
                      $scope.current_creature_template = $rootScope.fixNumericValues(data[0]);

                      $scope.selectionText += " (name: " + $scope.current_creature_template.name + ", entry: " + $scope.entityEntry + ")";
                    })
                      .error(function (data, status, header, config) {
                      console.log("[ERROR] creature/template/" + $scope.entityEntry + " $http.get request failed");
                    });
                  }
                }
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] creature/spawn/guid/" + $scope.entityGuid + " $http.get request failed");
              });

            } else {

              // Creature ENTRY
              $scope.entityEntry = $stateParams.entryOrGuid;

              /* Retrieve all creature_template datas */
              $http.get( app.api + "creature/template/" + $scope.entityEntry )
                .success(function (data, status, header, config) {
                $scope.current_creature_template = $rootScope.fixNumericValues(data[0]);

                $scope.selectionText += " (name: " + $scope.current_creature_template.name + ")";
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] creature/template/" + $scope.entityEntry + " $http.get request failed");
              });
            }
            break;

          case 1: // GameObject
            if ($stateParams.entryOrGuid < 0) {

              // GameObject GUID
              $scope.entityGuid = -$stateParams.entryOrGuid;

              /* Retrieve gameobject_template.entry */
              $http.get( app.api + "gameobject/spawn/guid/" + $scope.entityGuid)
                .success(function (data, status, header, config) {
                if (data.length < 1) {
                  console.log("[WARNING] gameobject/spawn/guid/" + $scope.entityGuid + " returned 0 results: unable to find the entry of the gameobject.");
                } else {
                  if (!data[0].hasOwnProperty('id')) {
                    console.log("[ERROR] gameobject/spawn/guid/" + $scope.entityGuid + " returned datas, but the attribute 'id' is not present.");
                  } else {
                    $scope.entityEntry = data[0].id;

                    /* Retrieve all gameobject_template datas */
                    $http.get( app.api + "gameobject/template/" + $scope.entityEntry )
                      .success(function (data, status, header, config) {
                      $scope.current_gameobject_template = $rootScope.fixNumericValues(data[0]);

                      $scope.selectionText += " (name: " + $scope.current_gameobject_template.name + ", entry: " + $scope.entityEntry + ")";
                    })
                      .error(function (data, status, header, config) {
                      console.log("[ERROR] gameobject/template/" + $scope.entityEntry + " $http.get request failed");
                    });
                  }
                }
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] gameobject/spawn/guid/" + $scope.entityGuid + " $http.get request failed");
              });

            } else {

              // GameObject ENTRY
              $scope.entityEntry = $stateParams.entryOrGuid;

              /* Retrieve all gameobject_template datas */
              $http.get( app.api + "gameobject/template/" + $scope.entityEntry )
                .success(function (data, status, header, config) {
                $scope.current_gameobject_template = $rootScope.fixNumericValues(data[0]);

                $scope.selectionText += " (name: " + $scope.current_gameobject_template.name + ")";
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] gameobject/template/" + $scope.entityEntry + " $http.get request failed");
              });
            }
            break;

          case 2: // AreaTrigger
            $scope.entityEntry = $stateParams.entryOrGuid;
            break;

          case 9: // Timed Actionlist
            $scope.entityEntry = $stateParams.entryOrGuid;
            break;

          default:
            console.log("[WARNING] source_type = " + $stateParams.sourceType + " not yet supported");
        }

      })
        .error(function (data, status, header, config) {
        console.log("[ERROR] smart_scripts/" + $stateParams.sourceType + "/" + $stateParams.entryOrGuid + " $http.get request failed");
      });

    } else {
      /* We have no creature selected and default active tab is search */
      $scope.isEntitySelected = false;
      $scope.saiTabs.search = true;
      $scope.selectionText = "No entity selected. Please use Search and select one.";
    }

    /* [Function] Search */
    $scope.search = function (sourceType, entryOrGuid, comment) {

      $http.get( app.api + "/smart_scripts/" + sourceType + "/" + entryOrGuid )
        .success(function (data, status, header, config) {
        if (data.length > 0) {
          $scope.exactResult.entryOrGuid    = data[0].entryorguid;
          $scope.exactResult.sourceType     = data[0].source_type;
          $scope.exactResult.sourceTypeName = $scope.sourceTypesConst[sourceType];
          $scope.foundExactResult = true;
        } else {
          $scope.foundExactResult = false;
        }
      })
        .error(function (data, status, header, config) {
        console.log("[ERROR] SMART SCRIPTS EXACT SEARCH $http.get request failed");
      });

      $http.get( app.api + "/search/smart_scripts/", {
        params: {
          source_type : sourceType,
          entryorguid : entryOrGuid,
          comment     : comment
        }
      }).success(function (data, status, header, config) {
        $scope.scripts = $rootScope.fixNumericValues(data);
      })
        .error(function (data, status, header, config) {
        console.log("[ERROR] SMART SCRIPTS SEARCH $http.get request failed");
      });

    };

    /* [Function] Open SQL SAI Script tab */
    $scope.openScriptTab = function() {
      $scope.generateSAIScript();
      $scope.saiTabs.search = false;
      $scope.saiTabs.create = false;
      $scope.saiTabs.editor = false;
      $scope.saiTabs.script = true;
    };

    /* [Function] Generate SQL SAI Script */
    $scope.generateSAIScript = function() {

      if (!$scope.isEntitySelected) {
        $scope.SAIScript = "-- No entity selected";
        return;
      }

      $scope.SAIScript = "-- " + $scope.selectionText + "\n\n";

      // non-smart_scripts datas
      switch (Number($stateParams.sourceType)) {

        case 0: // Creature
          $scope.SAIScript += "-- Table creature_template\n";
          $scope.SAIScript += "UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = " + $scope.entityEntry + ";\n\n";
          break;

        case 1: // GameObject
          $scope.SAIScript += "-- Table gameobject_template\n";
          $scope.SAIScript += "UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` = " + $scope.entityEntry + ";\n\n";
          break;

        case 2: // AreaTrigger
          $scope.SAIScript += "-- Table gameobject_template\n";
          $scope.SAIScript += "DELETE FROM `areatrigger_scripts` WHERE `entry` = " + $scope.entityEntry + ";\n";
          $scope.SAIScript += "INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES (" + $scope.entityEntry + ", 'SmartTrigger');\n\n";
          break;
      }

      // smart_scripts datas
      $scope.SAIScript += "-- Table smart_scripts\n";
      if ($scope.new_smart_scripts.length > 0) {
        $scope.SAIScript += app.getFullDeleteInsertTwoKeys("smart_scripts", "source_type", "entryorguid", $scope.new_smart_scripts);
      } else {
        $scope.SAIScript += "DELETE FROM `smart_scripts` WHERE (`source_type` = " + $stateParams.sourceType + " AND `entryorguid` = " + $stateParams.entryOrGuid + ");\n";
      }
    };

    /* [Function] disactive all tabs */
    $scope.disactiveAllTabs = function() {
      angular.forEach($scope.saiTabs, function(value, key) {
        value = false;
      });
    };

    /* [Function] open SQL Script tab */
    $scope.openScriptTab = function() {
      $scope.disactiveAllTabs();
      $scope.generateSAIScript();
      $scope.saiTabs.script = true;
    };

  });

}());
<commit_msg>SAI/Search prevent possible console.log error<commit_after>/*jslint browser: true, white: true, plusplus: true, eqeq: true, */
/*global angular, console, alert*/

(function () {
  'use strict';

  var app = angular.module('keira2');

  app.controller("SmartAIController", function ($rootScope, $scope, $http, $stateParams, $modal) {

    /* read ONLY values, do NOT bind them with ng-model in the view */
    $scope.sourceType = $stateParams.sourceType;
    $scope.entryOrGuid = $stateParams.sourceType;

    /* All SAI tabs, disabled by default.
    *  Only one tab can be active at a time */
    $scope.saiTabs = {
      search : false,
      create : false,
      editor : false,
      script : false
    };

    /* source_type constants */
    $scope.sourceTypesConst = {
      CREATURE          : 0, 0 : "Creature",
      GAMEOBJECT        : 1, 1 : "GameObject",
      AREATRIGGER       : 2, 2 : "AreaTrigger",
      EVENT             : 3, 3 : "Event",
      GOSSIP            : 4, 4 : "Gossip",
      QUEST             : 5, 5 : "Quest",
      SPELL             : 6, 6 : "Spell",
      TRANSPORT         : 7, 7 : "Transport",
      INSTANCE          : 8, 8 : "Instance",
      TIMED_ACTIONLIST  : 9, 9 : "Timed Actionlist"
    };

    /* Init arrays */
    $scope.exactResult            = [];
    $scope.search_smart_scripts   = [];
    $scope.new_smart_scripts      = [];
    $scope.current_smart_scripts  = [];

    /* Default source_type of search */
    $scope.search_smart_scripts.source_type = 0;

    /* Do not show exact result div in search by default */
    $scope.foundExactResult = false;

    /* Check if an entity (smart_scripts.source_type AND smart_scripts.entryorguid) is selected */
    if ($stateParams.sourceType && $stateParams.entryOrGuid) {

      /* We have a creature selected and default active tab is creatureTemplate */
      $scope.isEntitySelected = true;
      $scope.saiTabs.editor = true;

      /*  Following lines retrieve all SAI datas
       *  current_* mantains the database state
       *  new_*     mantains the editor state
       *  we will use those two objects to generate the SQL queries
       */

      /* Retrieve all smart_scripts datas */
      $http.get( app.api + "smart_scripts/" + $stateParams.sourceType + "/" + $stateParams.entryOrGuid )
        .success(function (data, status, header, config) {
        $scope.current_smart_scripts = $rootScope.fixNumericValues(data);
        $scope.new_smart_scripts = angular.copy($scope.current_smart_scripts);

        // check if we are editing an existing SAI script or creating a new one
        if ($scope.current_smart_scripts.length > 0) {
          // editing existing SAI script
          $scope.selectionText = "Editing the SmartAI script of ";
        } else {
          // creating new SAI script
          $scope.selectionText = "Creating a new SmartAI script for ";
        }

        $scope.selectionText += "[" +  $scope.sourceTypesConst[$stateParams.sourceType] + "] ";

        if ($stateParams.sourceType == 0 || $stateParams.sourceType == 1) {
          if ($stateParams.entryOrGuid > 0) {
            $scope.selectionText += "ENTRY ";
            $scope.selectionText += $stateParams.entryOrGuid;
          } else {
            $scope.selectionText += "GUID ";
            $scope.selectionText += -$stateParams.entryOrGuid;
          }
        } else {
          $scope.selectionText += $stateParams.entryOrGuid;
        }

        switch (Number($stateParams.sourceType)) {

          case 0: // Creature
            if ($stateParams.entryOrGuid < 0) {

              // Creature GUID
              $scope.entityGuid = -$stateParams.entryOrGuid;

              /* Retrieve creature_template.entry */
              $http.get( app.api + "creature/spawn/guid/" + $scope.entityGuid)
                .success(function (data, status, header, config) {
                if (data.length < 1) {
                  console.log("[WARNING] creature/spawn/guid/" + $scope.entityGuid + " returned 0 results: unable to find the entry of the creature.");
                } else {
                  if (!data[0].hasOwnProperty('id')) {
                    console.log("[ERROR] creature/spawn/guid/" + $scope.entityGuid + " returned datas, but the attribute 'id' is not present.");
                  } else {
                    $scope.entityEntry = data[0].id;

                    /* Retrieve all creature_template datas */
                    $http.get( app.api + "creature/template/" + $scope.entityEntry )
                      .success(function (data, status, header, config) {
                      $scope.current_creature_template = $rootScope.fixNumericValues(data[0]);

                      $scope.selectionText += " (name: " + $scope.current_creature_template.name + ", entry: " + $scope.entityEntry + ")";
                    })
                      .error(function (data, status, header, config) {
                      console.log("[ERROR] creature/template/" + $scope.entityEntry + " $http.get request failed");
                    });
                  }
                }
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] creature/spawn/guid/" + $scope.entityGuid + " $http.get request failed");
              });

            } else {

              // Creature ENTRY
              $scope.entityEntry = $stateParams.entryOrGuid;

              /* Retrieve all creature_template datas */
              $http.get( app.api + "creature/template/" + $scope.entityEntry )
                .success(function (data, status, header, config) {
                $scope.current_creature_template = $rootScope.fixNumericValues(data[0]);

                $scope.selectionText += " (name: " + $scope.current_creature_template.name + ")";
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] creature/template/" + $scope.entityEntry + " $http.get request failed");
              });
            }
            break;

          case 1: // GameObject
            if ($stateParams.entryOrGuid < 0) {

              // GameObject GUID
              $scope.entityGuid = -$stateParams.entryOrGuid;

              /* Retrieve gameobject_template.entry */
              $http.get( app.api + "gameobject/spawn/guid/" + $scope.entityGuid)
                .success(function (data, status, header, config) {
                if (data.length < 1) {
                  console.log("[WARNING] gameobject/spawn/guid/" + $scope.entityGuid + " returned 0 results: unable to find the entry of the gameobject.");
                } else {
                  if (!data[0].hasOwnProperty('id')) {
                    console.log("[ERROR] gameobject/spawn/guid/" + $scope.entityGuid + " returned datas, but the attribute 'id' is not present.");
                  } else {
                    $scope.entityEntry = data[0].id;

                    /* Retrieve all gameobject_template datas */
                    $http.get( app.api + "gameobject/template/" + $scope.entityEntry )
                      .success(function (data, status, header, config) {
                      $scope.current_gameobject_template = $rootScope.fixNumericValues(data[0]);

                      $scope.selectionText += " (name: " + $scope.current_gameobject_template.name + ", entry: " + $scope.entityEntry + ")";
                    })
                      .error(function (data, status, header, config) {
                      console.log("[ERROR] gameobject/template/" + $scope.entityEntry + " $http.get request failed");
                    });
                  }
                }
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] gameobject/spawn/guid/" + $scope.entityGuid + " $http.get request failed");
              });

            } else {

              // GameObject ENTRY
              $scope.entityEntry = $stateParams.entryOrGuid;

              /* Retrieve all gameobject_template datas */
              $http.get( app.api + "gameobject/template/" + $scope.entityEntry )
                .success(function (data, status, header, config) {
                $scope.current_gameobject_template = $rootScope.fixNumericValues(data[0]);

                $scope.selectionText += " (name: " + $scope.current_gameobject_template.name + ")";
              })
                .error(function (data, status, header, config) {
                console.log("[ERROR] gameobject/template/" + $scope.entityEntry + " $http.get request failed");
              });
            }
            break;

          case 2: // AreaTrigger
            $scope.entityEntry = $stateParams.entryOrGuid;
            break;

          case 9: // Timed Actionlist
            $scope.entityEntry = $stateParams.entryOrGuid;
            break;

          default:
            console.log("[WARNING] source_type = " + $stateParams.sourceType + " not yet supported");
        }

      })
        .error(function (data, status, header, config) {
        console.log("[ERROR] smart_scripts/" + $stateParams.sourceType + "/" + $stateParams.entryOrGuid + " $http.get request failed");
      });

    } else {
      /* We have no creature selected and default active tab is search */
      $scope.isEntitySelected = false;
      $scope.saiTabs.search = true;
      $scope.selectionText = "No entity selected. Please use Search and select one.";
    }

    /* [Function] Search */
    $scope.search = function (sourceType, entryOrGuid, comment) {

      if (sourceType != null && entryOrGuid != null) {
        $http.get( app.api + "/smart_scripts/" + sourceType + "/" + entryOrGuid )
          .success(function (data, status, header, config) {
          if (data.length > 0) {
            $scope.exactResult.entryOrGuid    = data[0].entryorguid;
            $scope.exactResult.sourceType     = data[0].source_type;
            $scope.exactResult.sourceTypeName = $scope.sourceTypesConst[sourceType];
            $scope.foundExactResult = true;
          } else {
            $scope.foundExactResult = false;
          }
        })
          .error(function (data, status, header, config) {
          console.log("[ERROR] SMART SCRIPTS EXACT SEARCH $http.get request failed");
        });
      }

      $http.get( app.api + "/search/smart_scripts/", {
        params: {
          source_type : sourceType,
          entryorguid : entryOrGuid,
          comment     : comment
        }
      }).success(function (data, status, header, config) {
        $scope.scripts = $rootScope.fixNumericValues(data);
      })
        .error(function (data, status, header, config) {
        console.log("[ERROR] SMART SCRIPTS SEARCH $http.get request failed");
      });

    };

    /* [Function] Open SQL SAI Script tab */
    $scope.openScriptTab = function() {
      $scope.generateSAIScript();
      $scope.saiTabs.search = false;
      $scope.saiTabs.create = false;
      $scope.saiTabs.editor = false;
      $scope.saiTabs.script = true;
    };

    /* [Function] Generate SQL SAI Script */
    $scope.generateSAIScript = function() {

      if (!$scope.isEntitySelected) {
        $scope.SAIScript = "-- No entity selected";
        return;
      }

      $scope.SAIScript = "-- " + $scope.selectionText + "\n\n";

      // non-smart_scripts datas
      switch (Number($stateParams.sourceType)) {

        case 0: // Creature
          $scope.SAIScript += "-- Table creature_template\n";
          $scope.SAIScript += "UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = " + $scope.entityEntry + ";\n\n";
          break;

        case 1: // GameObject
          $scope.SAIScript += "-- Table gameobject_template\n";
          $scope.SAIScript += "UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` = " + $scope.entityEntry + ";\n\n";
          break;

        case 2: // AreaTrigger
          $scope.SAIScript += "-- Table gameobject_template\n";
          $scope.SAIScript += "DELETE FROM `areatrigger_scripts` WHERE `entry` = " + $scope.entityEntry + ";\n";
          $scope.SAIScript += "INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES (" + $scope.entityEntry + ", 'SmartTrigger');\n\n";
          break;
      }

      // smart_scripts datas
      $scope.SAIScript += "-- Table smart_scripts\n";
      if ($scope.new_smart_scripts.length > 0) {
        $scope.SAIScript += app.getFullDeleteInsertTwoKeys("smart_scripts", "source_type", "entryorguid", $scope.new_smart_scripts);
      } else {
        $scope.SAIScript += "DELETE FROM `smart_scripts` WHERE (`source_type` = " + $stateParams.sourceType + " AND `entryorguid` = " + $stateParams.entryOrGuid + ");\n";
      }
    };

    /* [Function] disactive all tabs */
    $scope.disactiveAllTabs = function() {
      angular.forEach($scope.saiTabs, function(value, key) {
        value = false;
      });
    };

    /* [Function] open SQL Script tab */
    $scope.openScriptTab = function() {
      $scope.disactiveAllTabs();
      $scope.generateSAIScript();
      $scope.saiTabs.script = true;
    };

  });

}());
<|endoftext|>


<commit_before>$.fn.random = function() {
  return this.eq(Math.floor(Math.random() * this.length));
}

$(document).ready(function() {
    "use strict";

    var $ = window.jQuery;
    window.sliMpd = $.extend(true, window.sliMpd, {
        modules : {},
    });

    window.sliMpd.router = new window.sliMpd.modules.Router();

    window.Backbone.history.start({
    	pushState : true
    });
});<commit_msg>fixed indentations and usage of single/doublequotes<commit_after>$.fn.random = function() {
	return this.eq(Math.floor(Math.random() * this.length));
};

$(document).ready(function() {
	"use strict";
	var $ = window.jQuery;
	window.sliMpd = $.extend(true, window.sliMpd, {
		modules : {},
	});
	window.sliMpd.router = new window.sliMpd.modules.Router();
	window.Backbone.history.start({
		pushState : true
	});
});
<|endoftext|>


<commit_before>//==================================
//	Kyle Russell
//	github.com/denkers/GameTop100
//	site-controller
//==================================

(function()
{
	angular.module('main').controller('siteController', function($scope, $rootScope, $http)
	{
		$scope.selectedSite	=	null;

		$scope.saveComment	=	function(url, parent_site)
		{
			if(parent_site.selectedComment == null)
				$scope.addComment(url, parent_site);
			else
				$scope.editComment(url, parent_site);
		};

		$scope.addComment	=	function(url, parent_site)
		{
			var params		=	{ site_id: parent_site.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_content: parent_site.comment_add_field, comment_site: parent_site.id };

			console.log(url);
			$rootScope.postData(url, data, function(response)
			{
				parent_site.comment_response		=	response;
				parent_site.comment_response.show	=	true;

				if(response.status)
				{
					parent_site.comments.push(response.comment_data);
					parent_site.comment_add_field = '';
				}
			});
		};

		$scope.toggleCommentContainer = function(site)
		{
			site.showComments		=	!site.showComments;
			//$scope.selectedSite	=	$scope.selectedSite == index? null : index;
		};

		$scope.toggleEdit	=	function(comment, index, parent_site)
		{
			if(parent_site.selectedComment != null && parent_site.selectedComment != index)
			{
				var selectedComment			=	parent_site.comments[parent_site.selectedComment];
				selectedComment.isEdit		=	false;
			}

			var isEdit						=	comment.isEdit;
			parent_site.comment_add_field	=	(isEdit)? "" : comment.content;
			parent_site.selectedComment		=	(isEdit)? null : index;
			comment.isEdit					=	!comment.isEdit;
		};

		$scope.editComment	=	function(url, parent_site)
		{
			var comment		=	parent_site.comments[parent_site.selectedComment];
			var params		=	{ site_id: comment.site_id, comment_id: comment.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_content: comment.content, comment_id: comment.id };

			$rootScope.postData(url, data, function(response)
			{
				parent_site.comment_response		=	response;
				parent_site.comment_response.show	=	true;

				if(response.status)
				{
					comment.content					=	parent_site.comment_add_field;
					parent_site.comment_add_field	=	"";
					comment.isEdit					=	false;
					parent_site.selectedComment		=	null;
				}
			});
		};

		$scope.removeComment	=	function(url, comment, parent_site, index)
		{
			var params		=	{ site_id: comment.site_id, comment_id: comment.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_id: comment.id };

			$rootScope.postData(url, data, function(response)
			{
				parent_site.comment_response		=	response;
				parent_site.comment_response.show	=	true;

				if(response.status)
					parent_site.comments.splice(index, 1);
			});
		};

		$scope.hideCommentAlert	=	function(item)
		{
			item.comment_response.show	=	false;
		};

		$scope.voteComment	=	function(url, comment, parent_site, isUpvote)
		{
			var params		=	{ site_id: comment.site_id, comment_id: comment.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_id: comment.id, is_upvote: isUpvote };
			var voteBin		=	(isUpvote)? 1 : 0;

			$rootScope.postData(url, data, function(response)
			{
				if(response.status)
				{
					var amount	=	(comment.user_votes.length > 0)? 2 : 1;

					if(comment.user_votes.length > 0 && comment.user_votes[0].isUpvote == voteBin)
					{
						if(isUpvote)
							comment.comment_rating	=	parseInt(comment.comment_rating) - 1;
						else
							comment.comment_rating	=  parseInt(comment.comment_rating) + 1;

						comment.user_votes.splice(0, 1);
					}

					else
					{
						if(isUpvote)
							comment.comment_rating	=	parseInt(comment.comment_rating) + amount;
						else
							comment.comment_rating	=  parseInt(comment.comment_rating) - amount;

						if("added_vote" in response)
							comment.user_votes.push(response.added_vote);
						else
							comment.user_votes[0].isUpvote = voteBin;
					}
				}

				else
				{
					parent_site.comment_response		=	"Failed to save comment vote";
					parent_site.comment_response.show	=	true;
				}
			});

		};

		$scope.getSiteVoteCount	=	function(site)
		{
			var votes		=	site.votes;
			var voteCount	=	{ in_votes: 0, out_votes: 0 };

			if(votes.length > 0)
			{
				for(var i = 0; i < votes.length; i++)
				{
					var vote		=	votes[i];
					var num_votes	=	parseInt(vote.num_votes);

					if(vote.isOut == '1')
						voteCount.out_votes	=	num_votes;
					else
						voteCount.in_votes	=	num_votes;
				}
			}

			return voteCount;
		};
	});
})();
<commit_msg>Added redirectSite in controllers/site-controller for adding outgoing votes and redirecting users<commit_after>//==================================
//	Kyle Russell
//	github.com/denkers/GameTop100
//	site-controller
//==================================

(function()
{
	angular.module('main').controller('siteController', function($scope, $rootScope, $http)
	{
		$scope.selectedSite	=	null;

		$scope.saveComment	=	function(url, parent_site)
		{
			if(parent_site.selectedComment == null)
				$scope.addComment(url, parent_site);
			else
				$scope.editComment(url, parent_site);
		};

		$scope.addComment	=	function(url, parent_site)
		{
			var params		=	{ site_id: parent_site.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_content: parent_site.comment_add_field, comment_site: parent_site.id };

			console.log(url);
			$rootScope.postData(url, data, function(response)
			{
				parent_site.comment_response		=	response;
				parent_site.comment_response.show	=	true;

				if(response.status)
				{
					parent_site.comments.push(response.comment_data);
					parent_site.comment_add_field = '';
				}
			});
		};

		$scope.toggleCommentContainer = function(site)
		{
			site.showComments		=	!site.showComments;
			//$scope.selectedSite	=	$scope.selectedSite == index? null : index;
		};

		$scope.toggleEdit	=	function(comment, index, parent_site)
		{
			if(parent_site.selectedComment != null && parent_site.selectedComment != index)
			{
				var selectedComment			=	parent_site.comments[parent_site.selectedComment];
				selectedComment.isEdit		=	false;
			}

			var isEdit						=	comment.isEdit;
			parent_site.comment_add_field	=	(isEdit)? "" : comment.content;
			parent_site.selectedComment		=	(isEdit)? null : index;
			comment.isEdit					=	!comment.isEdit;
		};

		$scope.editComment	=	function(url, parent_site)
		{
			var comment		=	parent_site.comments[parent_site.selectedComment];
			var params		=	{ site_id: comment.site_id, comment_id: comment.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_content: comment.content, comment_id: comment.id };

			$rootScope.postData(url, data, function(response)
			{
				parent_site.comment_response		=	response;
				parent_site.comment_response.show	=	true;

				if(response.status)
				{
					comment.content					=	parent_site.comment_add_field;
					parent_site.comment_add_field	=	"";
					comment.isEdit					=	false;
					parent_site.selectedComment		=	null;
				}
			});
		};

		$scope.removeComment	=	function(url, comment, parent_site, index)
		{
			var params		=	{ site_id: comment.site_id, comment_id: comment.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_id: comment.id };

			$rootScope.postData(url, data, function(response)
			{
				parent_site.comment_response		=	response;
				parent_site.comment_response.show	=	true;

				if(response.status)
					parent_site.comments.splice(index, 1);
			});
		};

		$scope.hideCommentAlert	=	function(item)
		{
			item.comment_response.show	=	false;
		};

		$scope.voteComment	=	function(url, comment, parent_site, isUpvote)
		{
			var params		=	{ site_id: comment.site_id, comment_id: comment.id };
			url				=	$rootScope.setParams(url, params);
			var data		=	{ comment_id: comment.id, is_upvote: isUpvote };
			var voteBin		=	(isUpvote)? 1 : 0;

			$rootScope.postData(url, data, function(response)
			{
				if(response.status)
				{
					var amount	=	(comment.user_votes.length > 0)? 2 : 1;

					if(comment.user_votes.length > 0 && comment.user_votes[0].isUpvote == voteBin)
					{
						if(isUpvote)
							comment.comment_rating	=	parseInt(comment.comment_rating) - 1;
						else
							comment.comment_rating	=  parseInt(comment.comment_rating) + 1;

						comment.user_votes.splice(0, 1);
					}

					else
					{
						if(isUpvote)
							comment.comment_rating	=	parseInt(comment.comment_rating) + amount;
						else
							comment.comment_rating	=  parseInt(comment.comment_rating) - amount;

						if("added_vote" in response)
							comment.user_votes.push(response.added_vote);
						else
							comment.user_votes[0].isUpvote = voteBin;
					}
				}

				else
				{
					parent_site.comment_response		=	"Failed to save comment vote";
					parent_site.comment_response.show	=	true;
				}
			});

		};

		$scope.getSiteVoteCount	=	function(site)
		{
			var votes		=	site.votes;
			var voteCount	=	{ in_votes: 0, out_votes: 0 };

			if(votes.length > 0)
			{
				for(var i = 0; i < votes.length; i++)
				{
					var vote		=	votes[i];
					var num_votes	=	parseInt(vote.num_votes);

					if(vote.isOut == '1')
						voteCount.out_votes	=	num_votes;
					else
						voteCount.in_votes	=	num_votes;
				}
			}

			return voteCount;
		};

		$scope.redirectSite	=	function(site, outVoteUrl)
		{
			var params		=	{ site_id: site.id };
			outVoteUrl		=	$rootScope.setParams(outVoteUrl, params);
			var data		=	{ site-id: site.id };
			var msgTemplate	=	'<message-modal title="Redirect notice" message="Redirecting, one moment please"></message-modal>';
			$rootScope.openModal(template, null, 'siteController');

			setTimeout(function()
			{
				$rootScope.postData(outVoteUrl, data, function(response)
				{
					var url			=	site.address;
					window.location	=	url;
				});
			}, 1500);
		};
	});
})();
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { Trans, t } from '@lingui/macro';

import { findByBossId } from 'raids';
import lazyLoadComponent from 'common/lazyLoadComponent';
import retryingPromise from 'common/retryingPromise';
import makeWclUrl from 'common/makeWclUrl';
import Tooltip from 'common/Tooltip';
import { getResultTab } from 'interface/selectors/url/report';
import { hasPremium } from 'interface/selectors/user';
import ErrorBoundary from 'interface/common/ErrorBoundary';
import Warning from 'interface/common/Alert/Warning';
import Ad from 'interface/common/Ad';
import ReadableList from 'interface/common/ReadableList';
import Contributor from 'interface/contributor/Button';
import WipefestLogo from 'interface/images/Wipefest-logo.png';
import { i18n } from 'interface/RootLocalizationProvider';
import LoadingBar from 'interface/layout/NavigationBar/LoadingBar';
import Checklist from 'parser/shared/modules/features/Checklist/Module';
import StatTracker from 'parser/shared/modules/StatTracker';

import ChangelogTab from 'interface/others/ChangelogTab';
import Header from './Header';
import About from './About';
import Overview from './Overview';
import Statistics from './Statistics';
import Character from './Character';
import EncounterStats from './EncounterStats';
import './Results.scss';

// Gone for now, reintroduce if we can make it useful
// const DevelopmentTab = lazyLoadComponent(() => retryingPromise(() => import(/* webpackChunkName: 'DevelopmentTab' */ 'interface/others/DevelopmentTab').then(exports => exports.default)));
const TimelineTab = lazyLoadComponent(() => retryingPromise(() => import(/* webpackChunkName: 'TimelineTab' */ './Timeline/Container').then(exports => exports.default)));
const EventsTab = lazyLoadComponent(() => retryingPromise(() => import(/* webpackChunkName: 'EventsTab' */ 'interface/others/EventsTab').then(exports => exports.default)));

const CORE_TABS = {
  OVERVIEW: 'overview',
  STATISTICS: 'statistics',
  TIMELINE: 'timeline',
  CHARACTER: 'character',
  EVENTS: 'events',
  ABOUT: 'about',
};

class Results extends React.PureComponent {
  static propTypes = {
    parser: PropTypes.shape({
    }),
    characterProfile: PropTypes.object,
    selectedTab: PropTypes.string,
    makeTabUrl: PropTypes.func.isRequired,
    report: PropTypes.shape({
      code: PropTypes.string.isRequired,
    }).isRequired,
    fight: PropTypes.shape({
      start_time: PropTypes.number.isRequired,
      end_time: PropTypes.number.isRequired,
      boss: PropTypes.number.isRequired,
    }).isRequired,
    player: PropTypes.shape({
      name: PropTypes.string.isRequired,
    }).isRequired,
    isLoadingParser: PropTypes.bool,
    isLoadingEvents: PropTypes.bool,
    isLoadingBossPhaseEvents: PropTypes.bool,
    isLoadingCharacterProfile: PropTypes.bool,
    isParsingEvents: PropTypes.bool,
    progress: PropTypes.number,
    premium: PropTypes.bool,
  };
  static childContextTypes = {
    updateResults: PropTypes.func.isRequired,
    parser: PropTypes.object,
  };
  getChildContext() {
    return {
      updateResults: this.forceUpdate.bind(this),
      parser: this.props.parser,
    };
  }
  static contextTypes = {
    config: PropTypes.object.isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      adjustForDowntime: false,
    };
  }

  get warning() {
    const parser = this.props.parser;
    const boss = parser.boss;
    if (boss && boss.fight.resultsWarning) {
      return boss.fight.resultsWarning;
    }
    return null;
  }
  get isLoading() {
    return this.props.isLoadingParser
      || this.props.isLoadingEvents
      || this.props.isLoadingBossPhaseEvents
      || this.props.isLoadingCharacterProfile
      || this.props.isParsingEvents;
  }

  renderContent(selectedTab, results) {
    const { parser } = this.props;

    switch (selectedTab) {
      case CORE_TABS.OVERVIEW: {
        const checklist = parser.getModule(Checklist, false);
        return (
          <Overview
            checklist={checklist && checklist.render()}
            issues={results.issues}
          />
        );
      }
      case CORE_TABS.STATISTICS:
        return (
          <Statistics parser={parser}>{results.statistics}</Statistics>
        );
      case CORE_TABS.TIMELINE:
        return (
          <TimelineTab parser={parser} />
        );
      case CORE_TABS.EVENTS:
        return (

            <EventsTab parser={parser} />

        );
      case CORE_TABS.CHARACTER: {
        const statTracker = parser.getModule(StatTracker);

        return (

            <Character
              statTracker={statTracker}
              combatant={parser.selectedCombatant}
            />
            <EncounterStats
              currentBoss={parser.fight.boss}
              difficulty={parser.fight.difficulty}
              spec={parser.selectedCombatant._combatantInfo.specID}
              duration={parser.fight.end_time - parser.fight.start_time}
            />

        );
      }
      case CORE_TABS.ABOUT: {
        const config = this.context.config;
        return (

            <About config={config} />
            <ChangelogTab />

        );
      }
      default:
        return (

            {results.tabs.find(tab => tab.url === selectedTab).render()}

        );
    }
  }
  render() {
    const { parser, report, fight, player, characterProfile, makeTabUrl, selectedTab, premium, progress } = this.props;
    const config = this.context.config;

    const boss = findByBossId(fight.boss);

    const results = !this.isLoading && parser.generateResults({
      i18n, // TODO: Remove and use singleton
      adjustForDowntime: this.state.adjustForDowntime,
    });

    const contributorinfo = <ReadableList>{(config.contributors.length !== 0) ? config.contributors.map(contributor => <Contributor key={contributor.nickname} {...contributor} />) : 'CURRENTLY UNMAINTAINED'}</ReadableList>;

    return (
      <div className={`results boss-${fight.boss}`}>

        {boss && boss.fight.resultsWarning && (

            <Warning style={{ marginBottom: 30 }}>
              {boss.fight.resultsWarning}
            </Warning>

        )}

        {this.isLoading && (

            <LoadingBar progress={progress} />

              Loading spec analyzer...........{!this.props.isLoadingParser && 'OK'}

              Loading events for player.......{!this.props.isLoadingEvents && 'OK'}

              Loading phase events............{!this.props.isLoadingBossPhaseEvents && 'OK'}

              Loading character info..........{!this.props.isLoadingCharacterProfile && 'OK'}

              Analyzing events................{!this.props.isParsingEvents && 'OK'}

        )}

        {!this.isLoading && this.renderContent(selectedTab, results)}

        {premium === false && (

            <Ad />

        )}

              Provided by

                <Trans>{config.spec.specName} {config.spec.className} analysis has been provided by {contributorinfo}. They love hearing what you think, so please let them know! <Link to={makeTabUrl('about')}>More information about this spec's analyzer.</Link></Trans>

              View on

              <Tooltip content={i18n._(t`View the original report`)}>

                   Warcraft Logs

              </Tooltip>

              <Tooltip content={i18n._(t`View insights and timelines for raid encounters`)}>
                <a
                  href={`https://www.wipefest.net/report/${report.code}/fight/${fight.id}`}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="btn"
                  style={{ fontSize: 24, padding: '6px 0' }}
                >
                   Wipefest

              </Tooltip>

    );
  }
}

const mapStateToProps = state => ({
  selectedTab: getResultTab(state) || CORE_TABS.OVERVIEW,
  premium: hasPremium(state),
});

export default connect(
  mapStateToProps
)(Results);
<commit_msg>Add a mention about the target=_blank<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { Trans, t } from '@lingui/macro';

import { findByBossId } from 'raids';
import lazyLoadComponent from 'common/lazyLoadComponent';
import retryingPromise from 'common/retryingPromise';
import makeWclUrl from 'common/makeWclUrl';
import Tooltip from 'common/Tooltip';
import { getResultTab } from 'interface/selectors/url/report';
import { hasPremium } from 'interface/selectors/user';
import ErrorBoundary from 'interface/common/ErrorBoundary';
import Warning from 'interface/common/Alert/Warning';
import Ad from 'interface/common/Ad';
import ReadableList from 'interface/common/ReadableList';
import Contributor from 'interface/contributor/Button';
import WipefestLogo from 'interface/images/Wipefest-logo.png';
import { i18n } from 'interface/RootLocalizationProvider';
import LoadingBar from 'interface/layout/NavigationBar/LoadingBar';
import Checklist from 'parser/shared/modules/features/Checklist/Module';
import StatTracker from 'parser/shared/modules/StatTracker';

import ChangelogTab from 'interface/others/ChangelogTab';
import Header from './Header';
import About from './About';
import Overview from './Overview';
import Statistics from './Statistics';
import Character from './Character';
import EncounterStats from './EncounterStats';
import './Results.scss';

// Gone for now, reintroduce if we can make it useful
// const DevelopmentTab = lazyLoadComponent(() => retryingPromise(() => import(/* webpackChunkName: 'DevelopmentTab' */ 'interface/others/DevelopmentTab').then(exports => exports.default)));
const TimelineTab = lazyLoadComponent(() => retryingPromise(() => import(/* webpackChunkName: 'TimelineTab' */ './Timeline/Container').then(exports => exports.default)));
const EventsTab = lazyLoadComponent(() => retryingPromise(() => import(/* webpackChunkName: 'EventsTab' */ 'interface/others/EventsTab').then(exports => exports.default)));

const CORE_TABS = {
  OVERVIEW: 'overview',
  STATISTICS: 'statistics',
  TIMELINE: 'timeline',
  CHARACTER: 'character',
  EVENTS: 'events',
  ABOUT: 'about',
};

class Results extends React.PureComponent {
  static propTypes = {
    parser: PropTypes.shape({
    }),
    characterProfile: PropTypes.object,
    selectedTab: PropTypes.string,
    makeTabUrl: PropTypes.func.isRequired,
    report: PropTypes.shape({
      code: PropTypes.string.isRequired,
    }).isRequired,
    fight: PropTypes.shape({
      start_time: PropTypes.number.isRequired,
      end_time: PropTypes.number.isRequired,
      boss: PropTypes.number.isRequired,
    }).isRequired,
    player: PropTypes.shape({
      name: PropTypes.string.isRequired,
    }).isRequired,
    isLoadingParser: PropTypes.bool,
    isLoadingEvents: PropTypes.bool,
    isLoadingBossPhaseEvents: PropTypes.bool,
    isLoadingCharacterProfile: PropTypes.bool,
    isParsingEvents: PropTypes.bool,
    progress: PropTypes.number,
    premium: PropTypes.bool,
  };
  static childContextTypes = {
    updateResults: PropTypes.func.isRequired,
    parser: PropTypes.object,
  };
  getChildContext() {
    return {
      updateResults: this.forceUpdate.bind(this),
      parser: this.props.parser,
    };
  }
  static contextTypes = {
    config: PropTypes.object.isRequired,
  };

  constructor(props) {
    super(props);
    this.state = {
      adjustForDowntime: false,
    };
  }

  get warning() {
    const parser = this.props.parser;
    const boss = parser.boss;
    if (boss && boss.fight.resultsWarning) {
      return boss.fight.resultsWarning;
    }
    return null;
  }
  get isLoading() {
    return this.props.isLoadingParser
      || this.props.isLoadingEvents
      || this.props.isLoadingBossPhaseEvents
      || this.props.isLoadingCharacterProfile
      || this.props.isParsingEvents;
  }

  renderContent(selectedTab, results) {
    const { parser } = this.props;

    switch (selectedTab) {
      case CORE_TABS.OVERVIEW: {
        const checklist = parser.getModule(Checklist, false);
        return (
          <Overview
            checklist={checklist && checklist.render()}
            issues={results.issues}
          />
        );
      }
      case CORE_TABS.STATISTICS:
        return (
          <Statistics parser={parser}>{results.statistics}</Statistics>
        );
      case CORE_TABS.TIMELINE:
        return (
          <TimelineTab parser={parser} />
        );
      case CORE_TABS.EVENTS:
        return (

            <EventsTab parser={parser} />

        );
      case CORE_TABS.CHARACTER: {
        const statTracker = parser.getModule(StatTracker);

        return (

            <Character
              statTracker={statTracker}
              combatant={parser.selectedCombatant}
            />
            <EncounterStats
              currentBoss={parser.fight.boss}
              difficulty={parser.fight.difficulty}
              spec={parser.selectedCombatant._combatantInfo.specID}
              duration={parser.fight.end_time - parser.fight.start_time}
            />

        );
      }
      case CORE_TABS.ABOUT: {
        const config = this.context.config;
        return (

            <About config={config} />
            <ChangelogTab />

        );
      }
      default:
        return (

            {results.tabs.find(tab => tab.url === selectedTab).render()}

        );
    }
  }
  render() {
    const { parser, report, fight, player, characterProfile, makeTabUrl, selectedTab, premium, progress } = this.props;
    const config = this.context.config;

    const boss = findByBossId(fight.boss);

    const results = !this.isLoading && parser.generateResults({
      i18n, // TODO: Remove and use singleton
      adjustForDowntime: this.state.adjustForDowntime,
    });

    const contributorinfo = <ReadableList>{(config.contributors.length !== 0) ? config.contributors.map(contributor => <Contributor key={contributor.nickname} {...contributor} />) : 'CURRENTLY UNMAINTAINED'}</ReadableList>;

    return (
      <div className={`results boss-${fight.boss}`}>

        {boss && boss.fight.resultsWarning && (

            <Warning style={{ marginBottom: 30 }}>
              {boss.fight.resultsWarning}
            </Warning>

        )}

        {this.isLoading && (

            <LoadingBar progress={progress} />

              Loading spec analyzer...........{!this.props.isLoadingParser && 'OK'}

              Loading events for player.......{!this.props.isLoadingEvents && 'OK'}

              Loading phase events............{!this.props.isLoadingBossPhaseEvents && 'OK'}

              Loading character info..........{!this.props.isLoadingCharacterProfile && 'OK'}

              Analyzing events................{!this.props.isParsingEvents && 'OK'}

        )}

        {!this.isLoading && this.renderContent(selectedTab, results)}

        {premium === false && (

            <Ad />

        )}

              Provided by

                <Trans>{config.spec.specName} {config.spec.className} analysis has been provided by {contributorinfo}. They love hearing what you think, so please let them know! <Link to={makeTabUrl('about')}>More information about this spec's analyzer.</Link></Trans>

              View on

              <Tooltip content={i18n._(t`Opens in a new tab. View the original report.`)}>

                   Warcraft Logs

              </Tooltip>

              <Tooltip content={i18n._(t`Opens in a new tab. View insights and timelines for raid encounters.`)}>
                <a
                  href={`https://www.wipefest.net/report/${report.code}/fight/${fight.id}`}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="btn"
                  style={{ fontSize: 24, padding: '6px 0' }}
                >
                   Wipefest

              </Tooltip>

    );
  }
}

const mapStateToProps = state => ({
  selectedTab: getResultTab(state) || CORE_TABS.OVERVIEW,
  premium: hasPremium(state),
});

export default connect(
  mapStateToProps
)(Results);
<|endoftext|>


<commit_before>dc.ui.AccountDialog = dc.ui.Dialog.extend({

  id : 'account_list',

  callbacks : {
    '.ok.click'           : 'close',
    '.new_account.click'  : 'newAccount'
  },

  constructor : function() {
    this.base({
      mode      : 'custom',
      title     : dc.app.organization.name + ' group: ' + dc.app.organization.slug + ''
    });
    _.bindAll(this, '_renderAccounts');
    this._rendered = false;
    $(this.el).hide();
  },

  render : function() {
    this.base();
    this._rendered = true;
    $('.custom', this.el).html(JST.account_dialog({}));
    if (Accounts.current().isAdmin()) this.appendControl($.el('button', {'class': 'new_account'}, 'New Account'));
    this.list = $('#account_list_content', this.el);
    this.setCallbacks();
    dc.ui.spinner.show('loading');
    Accounts.populate({success : this._renderAccounts});
    return this;
  },

  open : function() {
    if (!this._rendered) return this.render();
    $(this.el).show();
  },

  close : function() {
    dc.ui.notifier.hide();
    $(this.el).hide();
  },

  newAccount : function() {
    var view = new dc.ui.AccountView({model : new dc.model.Account(), kind : 'row'});
    this.list.append(view.render('edit').el);
  },

  _renderAccounts : function() {
    dc.ui.spinner.hide();
    var views = _.map(Accounts.models(), function(account) {
      return (new dc.ui.AccountView({model : account, kind : 'row'})).render().el;
    });
    this.list.append(views);
    $(this.el).show();
    this.center();
  }

});
<commit_msg>scrolling to the bottom when new accounts are added<commit_after>dc.ui.AccountDialog = dc.ui.Dialog.extend({

  id : 'account_list',

  callbacks : {
    '.ok.click'           : 'close',
    '.new_account.click'  : 'newAccount'
  },

  constructor : function() {
    this.base({
      mode      : 'custom',
      title     : dc.app.organization.name + ' group: ' + dc.app.organization.slug + ''
    });
    _.bindAll(this, '_renderAccounts');
    this._rendered = false;
    $(this.el).hide();
  },

  render : function() {
    this.base();
    this._rendered = true;
    this._container = $('.custom', this.el);
    this._container.html(JST.account_dialog({}));
    if (Accounts.current().isAdmin()) this.appendControl($.el('button', {'class': 'new_account'}, 'New Account'));
    this.list = $('#account_list_content', this.el);
    this.setCallbacks();
    dc.ui.spinner.show('loading');
    Accounts.populate({success : this._renderAccounts});
    return this;
  },

  open : function() {
    if (!this._rendered) return this.render();
    $(this.el).show();
  },

  close : function() {
    dc.ui.notifier.hide();
    $(this.el).hide();
  },

  newAccount : function() {
    var view = new dc.ui.AccountView({model : new dc.model.Account(), kind : 'row'});
    this.list.append(view.render('edit').el);
    this._container[0].scrollTop = this._container[0].scrollHeight;
  },

  _renderAccounts : function() {
    dc.ui.spinner.hide();
    var views = _.map(Accounts.models(), function(account) {
      return (new dc.ui.AccountView({model : account, kind : 'row'})).render().el;
    });
    this.list.append(views);
    $(this.el).show();
    this.center();
  }

});
<|endoftext|>


<commit_before>console.log( "=== simpread site load ===" )

/**
 * Get URI
 *
 * @return {string} e.g. current site url is http://www.cnbeta.com/articles/1234.html return http://www.cnbeta.com/articles/
 */
function getURI() {
    //const arr = window.location.pathname.match( /(\S+\/\b|^\/)/g );
    //return `${ window.location.protocol }//${ window.location.hostname }${ arr[0] }`;
    const name = (pathname) => {
        pathname = pathname != "/" && pathname.endsWith("/") ? pathname = pathname.replace( /\/$/, "" ) : pathname;
        return pathname.replace( /\/[@#.~a-zA-Z0-9_-]+$|^\/$/g, "" );
    },
    path = name( window.location.pathname );
    return `${ window.location.protocol }//${ window.location.hostname }${ path }/`;
}

/**
 * Find site by url from simpread.sites, include wildcard, support: *
 *
 * @param  {map}    simpread.sites
 * @param  {string} url
 * @return {array}  0: current site; 1: current url
 */
function findSitebyURL( sites, url ) {
    const domain   = (names)=>{
            const arr = names.replace( "www.", "" ).match( /\.\S+\.\S+/g );
            if ( arr ) {
                return arr[0].substr(1);
            } else {
                return names.replace( "www.", "" );
            }
          },
          urls     = [ ...sites.keys() ],
          arr      = url.match( /[.a-zA-z0-9-_]+/g ),
          uri      = arr[1].replace( "www.", "" ),
          hostname = domain( window.location.hostname ),
          isroot   = ()=>window.location.pathname == "/" || /\/(default|index|portal).[0-9a-zA-Z]+$/.test(window.location.pathname);
    let   found;
    for ( const cur of urls ) {
        const name   = sites.get(cur).name,
              sufname= domain( name );
        if ( !isroot() && !cur.endsWith( "*" ) && cur == url ) {
            found = cur;
            break;
        }
        else if ( !isroot() && cur.endsWith( "*" ) && uri.includes( sufname ) && hostname == sufname && url.includes( name ) ) {
            //if ( /\/[a-zA-Z0-9]+\/\*/g.test( cur )) {
            //    if    ( suffix != url ) return undefined;
            //} else if ( suffix == url ) return undefined;
            found = cur;
            break;
        }
    }
    if ( found ) {
        return [ clone( sites.get( found )), found ];
    }
    return undefined;
}

/**
 * Remove spare tag
 *
 * @param {string} storage.current.site.name
 * @param {jquery} jquery object
 */
async function removeSpareTag( name, $target ) {
    let [ remove, tag ] = [ false, "" ];
    if ([ "lib.csdn.net", "huxiu.com", "my.oschina.net", "caixin.com", "163.com", "steachs.com", "hacpai.com", "apprcn.com", "mp.weixin.qq.com" ].includes( name )) {
        [ remove, tag ] = [ true, "p" ];
    } else if ([ "nationalgeographic.com.cn", "dgtle.com", "news.mtime.com" ].includes( name )) {
        [ remove, tag ] = [ true, "div" ];
    } else if ( ["chiphell.com"].includes( name ) ) {
        [ remove, tag ] = [ true, "font" ];
    }
    if ( remove ) {
        $target.find( tag ).map( ( index, item ) => {
            const str = $(item).text().toLowerCase().trim();
            if ( $(item).find( "img" ).length == 0 && str == "" ) $(item).remove();
        });
    }
}

/**
 * Verify site
 *
 * @param  {string} storage.current.site.name
 * @return {number} 0: success; -1: not exsit; -2: tieba.com; -3: chiphell.com
 */
function verify( name ) {
    const [ hostname, pathname, href ] = [ window.location.hostname, window.location.pathname, window.location.href ];
    if ( hostname == "tieba.baidu.com" && !href.includes( "see_lz=1" ) ) {
        return -2;
    } else if ( hostname == "www.chiphell.com" ) {
        if ( pathname == "/forum.php" && window.location.search.includes( "mod=viewthread" ) ) {
            return 0;
        } else if ( pathname.includes( "thread" ) && window.location.search == "" ) {
            return -3;
        } else {
            return -1;
        }
    } else if ( name === "" ) {
        return -1;
    } else {
        return 0;
    }
}

/**
 * Beautify html
 *
 * @param {string} storage.current.site.name
 */
async function specbeautify( name, $target ) {
    switch ( name ) {
        case "sspai.com":
            $target.find( ".relation-apps" ).map( (index, item) => {
                // TO-DO
                $(item).remove();
            });
            break;
        case "post.smzdm.com":
            $target.find( "img.face" ).addClass( "sr-rd-content-nobeautify" );
            $target.find( ".insert-outer img" ).addClass( "sr-rd-content-nobeautify" );
            break;
        case "infoq.com":
            $target.find( "img" ).map( (index, item) => {
                if ( $(item).css("float") == "left" ) {
                    $(item).addClass( "sr-rd-content-nobeautify" );
                }
            });
            break;
        case "appinn.com":
            $target.find( ".emoji" ).addClass( "sr-rd-content-nobeautify" );
            break;
        case "hacpai.com":
            $target.find( ".emoji" ).addClass( "sr-rd-content-nobeautify" );
            break;
        case "douban.com":
            $target.find( ".review-content" ).children().unwrap();
            $target.find( "table" ).addClass( "sr-rd-content-center" );
            $target.find( "p" ).css({"white-space": "pre-wrap"});
            $target.find( ".cc" ).removeClass();
            break;
        case "qdaily.com":
            $target.find( "img" ).map( (index, item) => {
                const $target = $(item),
                      height  = Number.parseInt($target.css("height"));
                if ( height == 0 ) $target.remove();
            });
            $target.find( ".com-insert-images" ).map( (index, item) => {
                const $target = $(item),
                      imgs    = $target.find( "img" ).map( (index, item)=>`<div>${item.outerHTML}</div>` ),
                      str     = imgs.get().join( "" );
                $target.empty().removeAttr( "class" ).append( str );
            });
            $target.find( ".com-insert-embed" ).remove();
            break;
        case "news.mtime.com":
            $target.find( ".newspictool" ).map( ( index, item ) => {
                const $target = $(item),
                      $img    = $target.find( "img" ),
                      $label  = $target.find( "p:last" );
                $target.removeAttr( "class" ).addClass( "sr-rd-content-center" ).empty().append( $img ).append( $label );
            });
            break;
        case "blog.csdn.net":
            $target.find( ".save_code" ).remove();
            $target.find( ".pre-numbering" ).remove();
            $target.find( "pre" ).removeAttr( "style" ).removeAttr( "class" );
            $target.find( "code" ).removeAttr( "style" );
            $target.find( ".dp-highlighter" ).map( ( index, item )=> {
                $(item).find(".bar .tools").remove();
                if ( $(item).next().is( "pre" )) $(item).next().remove();
            });
            break;
        case "news.sohu.com":
            $target.find( ".conserve-photo" ).remove();
            $target.find( "table" ).addClass( "sr-rd-content-center" );
            break;
        case "qq.com":
            $target.find( ".rv-root-v2, #backqqcom" ).remove();
            break;
        case "azofreeware.com":
            $target.find( "iframe" ).remove();
            break;
        case "apprcn.com":
            $target.find( "img" ).map( ( index, item ) => {
                const $target = $(item),
                      src     = $target.attr( "src" );
                if ( src && src.includes( "Apprcn_Wechat_Small.jpeg" ) ) $target.parent().remove();
            });
            $target.find( "a" ).map( ( index, item ) => {
                const $target = $(item),
                      text    = $target.text();
                if ( text == "来自反斗软件" ) $target.parent().remove();
            });
            break;
        case "tieba.baidu.com":
            $target.find( ".BDE_Smiley" ).addClass( "sr-rd-content-nobeautify" );
            $target.find( ".replace_div" ).removeAttr( "class" ).removeAttr( "style" );
            $target.find( ".replace_tip" ).remove();
            break;
        case "question.zhihu.com":
            $target.find( ".zu-edit-button" ).remove();
            break;
        case "chiphell.com":
            $target.find( "img" ).map( ( index, item ) => {
                const $target = $(item),
                      $parent = $target.parent(),
                      src     = $target.attr( "src" );
                if ( $parent.is( "ignore_js_op" )) $target.unwrap();
                if ( src && src.includes( "static/image/smiley" ) ) $target.addClass( "sr-rd-content-nobeautify" );
            });
            $target.find( ".quote" ).remove();
            break;
        case "jiemian.com":
            $target.find( "script" ).remove();
            break;
        case "36kr.com":
            $target.find( ".load-html-img" ).removeAttr( "class" );
            break;
        case "cnblogs.com":
            $target.find( ".cnblogs_code" ).removeClass();
            $target.find( ".cnblogs_code_toolbar" ).remove();
            break;
        case "news.cnblogs.com":
            $target.find( ".topic_img" ).remove();
            break;
        case "g-cores.com":
            $target.find( ".swiper-slide-active" ).find( "img" ).map( ( index, item ) => {
                const $target = $(item);
                $target.parent().parent().parent().parent().parent().parent().removeAttr( "class" ).removeAttr( "style" ).html($target);
            });
            break;
        case "feng.com":
            $target.find( "span" ).removeAttr( "style" );
            break;
        case "young.ifeng.com":
            $target.find( "span" ).removeAttr( "style" );
            break;
        case "ftchinese.com":
            $target.find( "script" ).remove();
            break;
        case "segmentfault.com":
            $target.find( ".widget-codetool" ).remove();
            break;
    }
}

/**
 * Deep clone object
 *
 * @param  {object} target object
 * @return {object} new target object
 */
function clone( target ) {
    return $.extend( true, {}, target );
}

export {
    getURI         as GetURI,
    findSitebyURL  as Getsite,
    specbeautify   as Beautify,
    removeSpareTag as RemoveTag,
    verify         as Verify
}<commit_msg>Add new task by mp.weixin.qq.com.<commit_after>console.log( "=== simpread site load ===" )

/**
 * Get URI
 *
 * @return {string} e.g. current site url is http://www.cnbeta.com/articles/1234.html return http://www.cnbeta.com/articles/
 */
function getURI() {
    //const arr = window.location.pathname.match( /(\S+\/\b|^\/)/g );
    //return `${ window.location.protocol }//${ window.location.hostname }${ arr[0] }`;
    const name = (pathname) => {
        pathname = pathname != "/" && pathname.endsWith("/") ? pathname = pathname.replace( /\/$/, "" ) : pathname;
        return pathname.replace( /\/[@#.~a-zA-Z0-9_-]+$|^\/$/g, "" );
    },
    path = name( window.location.pathname );
    return `${ window.location.protocol }//${ window.location.hostname }${ path }/`;
}

/**
 * Find site by url from simpread.sites, include wildcard, support: *
 *
 * @param  {map}    simpread.sites
 * @param  {string} url
 * @return {array}  0: current site; 1: current url
 */
function findSitebyURL( sites, url ) {
    const domain   = (names)=>{
            const arr = names.replace( "www.", "" ).match( /\.\S+\.\S+/g );
            if ( arr ) {
                return arr[0].substr(1);
            } else {
                return names.replace( "www.", "" );
            }
          },
          urls     = [ ...sites.keys() ],
          arr      = url.match( /[.a-zA-z0-9-_]+/g ),
          uri      = arr[1].replace( "www.", "" ),
          hostname = domain( window.location.hostname ),
          isroot   = ()=>window.location.pathname == "/" || /\/(default|index|portal).[0-9a-zA-Z]+$/.test(window.location.pathname);
    let   found;
    for ( const cur of urls ) {
        const name   = sites.get(cur).name,
              sufname= domain( name );
        if ( !isroot() && !cur.endsWith( "*" ) && cur == url ) {
            found = cur;
            break;
        }
        else if ( !isroot() && cur.endsWith( "*" ) && uri.includes( sufname ) && hostname == sufname && url.includes( name ) ) {
            //if ( /\/[a-zA-Z0-9]+\/\*/g.test( cur )) {
            //    if    ( suffix != url ) return undefined;
            //} else if ( suffix == url ) return undefined;
            found = cur;
            break;
        }
    }
    if ( found ) {
        return [ clone( sites.get( found )), found ];
    }
    return undefined;
}

/**
 * Remove spare tag
 *
 * @param {string} storage.current.site.name
 * @param {jquery} jquery object
 */
async function removeSpareTag( name, $target ) {
    let [ remove, tag ] = [ false, "" ];
    if ([ "lib.csdn.net", "huxiu.com", "my.oschina.net", "caixin.com", "163.com", "steachs.com", "hacpai.com", "apprcn.com", "mp.weixin.qq.com" ].includes( name )) {
        [ remove, tag ] = [ true, "p" ];
    } else if ([ "nationalgeographic.com.cn", "dgtle.com", "news.mtime.com" ].includes( name )) {
        [ remove, tag ] = [ true, "div" ];
    } else if ( ["chiphell.com"].includes( name ) ) {
        [ remove, tag ] = [ true, "font" ];
    }
    if ( remove ) {
        $target.find( tag ).map( ( index, item ) => {
            const str = $(item).text().toLowerCase().trim();
            if ( $(item).find( "img" ).length == 0 && str == "" ) $(item).remove();
        });
    }
}

/**
 * Verify site
 *
 * @param  {string} storage.current.site.name
 * @return {number} 0: success; -1: not exsit; -2: tieba.com; -3: chiphell.com
 */
function verify( name ) {
    const [ hostname, pathname, href ] = [ window.location.hostname, window.location.pathname, window.location.href ];
    if ( hostname == "tieba.baidu.com" && !href.includes( "see_lz=1" ) ) {
        return -2;
    } else if ( hostname == "www.chiphell.com" ) {
        if ( pathname == "/forum.php" && window.location.search.includes( "mod=viewthread" ) ) {
            return 0;
        } else if ( pathname.includes( "thread" ) && window.location.search == "" ) {
            return -3;
        } else {
            return -1;
        }
    } else if ( name === "" ) {
        return -1;
    } else {
        return 0;
    }
}

/**
 * Beautify html
 *
 * @param {string} storage.current.site.name
 */
async function specbeautify( name, $target ) {
    switch ( name ) {
        case "sspai.com":
            $target.find( ".relation-apps" ).map( (index, item) => {
                // TO-DO
                $(item).remove();
            });
            break;
        case "post.smzdm.com":
            $target.find( "img.face" ).addClass( "sr-rd-content-nobeautify" );
            $target.find( ".insert-outer img" ).addClass( "sr-rd-content-nobeautify" );
            break;
        case "infoq.com":
            $target.find( "img" ).map( (index, item) => {
                if ( $(item).css("float") == "left" ) {
                    $(item).addClass( "sr-rd-content-nobeautify" );
                }
            });
            break;
        case "appinn.com":
            $target.find( ".emoji" ).addClass( "sr-rd-content-nobeautify" );
            break;
        case "hacpai.com":
            $target.find( ".emoji" ).addClass( "sr-rd-content-nobeautify" );
            break;
        case "douban.com":
            $target.find( ".review-content" ).children().unwrap();
            $target.find( "table" ).addClass( "sr-rd-content-center" );
            $target.find( "p" ).css({"white-space": "pre-wrap"});
            $target.find( ".cc" ).removeClass();
            break;
        case "qdaily.com":
            $target.find( "img" ).map( (index, item) => {
                const $target = $(item),
                      height  = Number.parseInt($target.css("height"));
                if ( height == 0 ) $target.remove();
            });
            $target.find( ".com-insert-images" ).map( (index, item) => {
                const $target = $(item),
                      imgs    = $target.find( "img" ).map( (index, item)=>`<div>${item.outerHTML}</div>` ),
                      str     = imgs.get().join( "" );
                $target.empty().removeAttr( "class" ).append( str );
            });
            $target.find( ".com-insert-embed" ).remove();
            break;
        case "news.mtime.com":
            $target.find( ".newspictool" ).map( ( index, item ) => {
                const $target = $(item),
                      $img    = $target.find( "img" ),
                      $label  = $target.find( "p:last" );
                $target.removeAttr( "class" ).addClass( "sr-rd-content-center" ).empty().append( $img ).append( $label );
            });
            break;
        case "blog.csdn.net":
            $target.find( ".save_code" ).remove();
            $target.find( ".pre-numbering" ).remove();
            $target.find( "pre" ).removeAttr( "style" ).removeAttr( "class" );
            $target.find( "code" ).removeAttr( "style" );
            $target.find( ".dp-highlighter" ).map( ( index, item )=> {
                $(item).find(".bar .tools").remove();
                if ( $(item).next().is( "pre" )) $(item).next().remove();
            });
            break;
        case "news.sohu.com":
            $target.find( ".conserve-photo" ).remove();
            $target.find( "table" ).addClass( "sr-rd-content-center" );
            break;
        case "qq.com":
            $target.find( ".rv-root-v2, #backqqcom" ).remove();
            break;
        case "azofreeware.com":
            $target.find( "iframe" ).remove();
            break;
        case "apprcn.com":
            $target.find( "img" ).map( ( index, item ) => {
                const $target = $(item),
                      src     = $target.attr( "src" );
                if ( src && src.includes( "Apprcn_Wechat_Small.jpeg" ) ) $target.parent().remove();
            });
            $target.find( "a" ).map( ( index, item ) => {
                const $target = $(item),
                      text    = $target.text();
                if ( text == "来自反斗软件" ) $target.parent().remove();
            });
            break;
        case "tieba.baidu.com":
            $target.find( ".BDE_Smiley" ).addClass( "sr-rd-content-nobeautify" );
            $target.find( ".replace_div" ).removeAttr( "class" ).removeAttr( "style" );
            $target.find( ".replace_tip" ).remove();
            break;
        case "question.zhihu.com":
            $target.find( ".zu-edit-button" ).remove();
            break;
        case "chiphell.com":
            $target.find( "img" ).map( ( index, item ) => {
                const $target = $(item),
                      $parent = $target.parent(),
                      src     = $target.attr( "src" );
                if ( $parent.is( "ignore_js_op" )) $target.unwrap();
                if ( src && src.includes( "static/image/smiley" ) ) $target.addClass( "sr-rd-content-nobeautify" );
            });
            $target.find( ".quote" ).remove();
            break;
        case "jiemian.com":
            $target.find( "script" ).remove();
            break;
        case "36kr.com":
            $target.find( ".load-html-img" ).removeAttr( "class" );
            break;
        case "cnblogs.com":
            $target.find( ".cnblogs_code" ).removeClass();
            $target.find( ".cnblogs_code_toolbar" ).remove();
            break;
        case "news.cnblogs.com":
            $target.find( ".topic_img" ).remove();
            break;
        case "g-cores.com":
            $target.find( ".swiper-slide-active" ).find( "img" ).map( ( index, item ) => {
                const $target = $(item);
                $target.parent().parent().parent().parent().parent().parent().removeAttr( "class" ).removeAttr( "style" ).html($target);
            });
            break;
        case "feng.com":
            $target.find( "span" ).removeAttr( "style" );
            break;
        case "young.ifeng.com":
            $target.find( "span" ).removeAttr( "style" );
            break;
        case "ftchinese.com":
            $target.find( "script" ).remove();
            break;
        case "segmentfault.com":
            $target.find( ".widget-codetool" ).remove();
            break;
        case "mp.weixin.qq.com":
            $target.find( 'section[powered-by="xiumi.us"]' ).find( "img" ).map( ( index, item ) => {
                const $target = $(item),
                      src     = $target.attr( "data-src" );
                $target.addClass( "sr-rd-content-nobeautify" ).attr( "src", src );
            });
            break;
    }
}

/**
 * Deep clone object
 *
 * @param  {object} target object
 * @return {object} new target object
 */
function clone( target ) {
    return $.extend( true, {}, target );
}

export {
    getURI         as GetURI,
    findSitebyURL  as Getsite,
    specbeautify   as Beautify,
    removeSpareTag as RemoveTag,
    verify         as Verify
}<|endoftext|>


<commit_before>// Category View
// =============

// Includes file dependencies
define([
    "underscore",
    "jquery",
    "backbone",
    "marionette",
    "parse",
    "moment",
    "text!../templates/character-print-view.html",
    "text!../templates/character-history-selected-view.html",
    "text!../templates/character-history-view.html",
    "../helpers/VampirePrintHelper"
], function( _, $, Backbone, Marionette, Parse, moment, character_print_view_html, character_history_selected_view_html, character_history_view_html, VampirePrintHelper) {

    var MainView = Marionette.ItemView.extend({
        template: _.template(character_history_view_html),
        templateHelpers: function () {
            var self = this;
            return {
                "character": this.model,
                "logs": this.model.recorded_changes.models,
                idForPickedIndex: self.picked.get("value")
            }
        },
        modelEvents: {
            "saved": "update_then_render"
        },
        events: {
            "change": "update_picked"
        },
        initialize: function(options) {
            this.picked = options.picked;
            this.override = options.override;

            _.bindAll(this, "templateHelpers");
        },
        update_picked: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            self.picked.set("value", selectedIndex);

            var selectedId = this.$("#history-changes-" + selectedIndex).val();
            var changesToApply = _.chain(self.model.recorded_changes.models).takeRightWhile(function (model) {
                return model.id != selectedId;
            }).reverse().value();
            var c = self.model.get_transformed(changesToApply);
            self.override.set("character", c);
        },
        update_then_render: function() {
            var self = this;
            self.model.update_recorded_changes().then(function () {
                self.render();
            });
        },
        onRender: function() {
            this.$el.enhanceWithin();
        }
    });

    var ViewingView = Marionette.ItemView.extend({
        template: _.template(character_history_selected_view_html),
        templateHelpers: function () {
            var self = this;
            return {
                "character": this.model,
                "logs": this.model.recorded_changes.models,
                "format_entry": this.format_entry,
                idForPickedIndex: self.picked.get("value")
            }
        },
        modelEvents: {
            "add": "render",
            "reset": "render"
        },
        initialize: function(options) {
            this.picked = options.picked;

            this.listenTo(
                this.picked,
                "change",
                _.debounce(this.render, 100, { trailing: true}));

            _.bindAll(this, "templateHelpers");
        },
        format_entry: function(log, entry) {
            if (_.isUndefined(log)) {
                console.log("Undefined log");
                return "Undefined log";
            }
            if (log.get(entry)) {
                return log.get(entry);
            }
            var attr = log[entry];
            if (_.isDate(attr)) {
                return moment(attr).format('lll');
            }
            return attr;
        },
        onRender: function() {
            this.$el.enhanceWithin();
        }
    });

    var SheetView = Marionette.ItemView.extend({
        template: _.template(character_print_view_html),
        templateHelpers: function () {
            var self = this;
            var character = self.override.get("character") || self.model
            var sortedSkills = character.get_sorted_skills();
            return {
                "character": character,
                "skills": sortedSkills,
                "groupedSkills": character.get_grouped_skills(sortedSkills),
                format_simpletext: this.format_simpletext,
                format_attribute_value: this.format_attribute_value,
                format_attribute_focus: this.format_attribute_focus,
                format_skill: this.format_skill,
                format_specializations: this.format_specializations
            }
        },
        modelEvents: {
            "change": "renderIfNoOverride",
        },
        initialize: function(options) {
            this.override = options.override;
            this.listenTo(
                this.override,
                "change",
                _.debounce(this.render, 100, { trailing: true}));

            _.bindAll(
                this,
                "templateHelpers",
                "format_simpletext",
                "format_attribute_value",
                "format_attribute_focus",
                "format_skill",
                "format_specializations"
            );

        },
        renderIfNoOverride: function() {
            var self = this;
            if (self.override.get("character") == null) {
                return;
            }
            return self.render();
        },
        onRender: function() {
            this.$el.enhanceWithin();
        }
    })
    _.extend(SheetView.prototype, VampirePrintHelper);

    var LayoutView = Marionette.LayoutView.extend({
        tagName: "div",
        regions: {
            main: "#history-main",
            viewing: "#history-viewing",
            sheet: "#history-sheet"
        },

        register: function(model) {
            var self = this;
            var p = Parse.Promise.as([]);

            if (model != self.model) {
                self.model = model;
                self.picked = new Backbone.Model({value: 0});
                self.override = new Backbone.Model({character: null});

                p = self.model.get_recorded_changes().then(function () {
                    self.picked.set("value", self.model.recorded_changes.models.length - 1);

                    // Set up child views now
                    self.showChildView('main', new MainView({
                        model: self.model,
                        picked: self.picked,
                        override: self.override
                    }));
                    self.showChildView('viewing', new ViewingView({
                        model: self.model,
                        picked: self.picked
                    }));
                    self.showChildView('sheet', new SheetView({
                        model: self.model,
                        override: self.override
                    }));
                });
            }

            return p.then(function () {
                Parse.Promise.as(self);
            });
        },
        onRender: function () {
            this.$el.enhanceWithin();
        }
    });

    return LayoutView;

} );<commit_msg>Use print view directly in history view<commit_after>// Category View
// =============

// Includes file dependencies
define([
    "underscore",
    "jquery",
    "backbone",
    "marionette",
    "parse",
    "moment",
    "text!../templates/character-print-view.html",
    "text!../templates/character-history-selected-view.html",
    "text!../templates/character-history-view.html",
    "../helpers/VampirePrintHelper",
    "../views/CharacterPrintView"
], function( _, $, Backbone, Marionette, Parse, moment, character_print_view_html, character_history_selected_view_html, character_history_view_html, VampirePrintHelper, CharacterPrintView ) {

    var MainView = Marionette.ItemView.extend({
        template: _.template(character_history_view_html),
        templateHelpers: function () {
            var self = this;
            return {
                "character": this.model,
                "logs": this.model.recorded_changes.models,
                idForPickedIndex: self.picked.get("value")
            }
        },
        modelEvents: {
            "saved": "update_then_render"
        },
        events: {
            "change": "update_picked"
        },
        initialize: function(options) {
            this.picked = options.picked;
            this.override = options.override;

            _.bindAll(this, "templateHelpers");
        },
        update_picked: function (e) {
            var self = this;
            var selectedIndex = _.parseInt(this.$(e.target).val());
            self.picked.set("value", selectedIndex);

            var selectedId = this.$("#history-changes-" + selectedIndex).val();
            var changesToApply = _.chain(self.model.recorded_changes.models).takeRightWhile(function (model) {
                return model.id != selectedId;
            }).reverse().value();
            var c = self.model.get_transformed(changesToApply);
            self.override.set("character", c);
        },
        update_then_render: function() {
            var self = this;
            self.model.update_recorded_changes().then(function () {
                self.render();
            });
        },
        onRender: function() {
            this.$el.enhanceWithin();
        }
    });

    var ViewingView = Marionette.ItemView.extend({
        template: _.template(character_history_selected_view_html),
        templateHelpers: function () {
            var self = this;
            return {
                "character": this.model,
                "logs": this.model.recorded_changes.models,
                "format_entry": this.format_entry,
                idForPickedIndex: self.picked.get("value")
            }
        },
        modelEvents: {
            "add": "render",
            "reset": "render"
        },
        initialize: function(options) {
            this.picked = options.picked;

            this.listenTo(
                this.picked,
                "change",
                _.debounce(this.render, 100, { trailing: true}));

            _.bindAll(this, "templateHelpers");
        },
        format_entry: function(log, entry) {
            if (_.isUndefined(log)) {
                console.log("Undefined log");
                return "Undefined log";
            }
            if (log.get(entry)) {
                return log.get(entry);
            }
            var attr = log[entry];
            if (_.isDate(attr)) {
                return moment(attr).format('lll');
            }
            return attr;
        },
        onRender: function() {
            this.$el.enhanceWithin();
        }
    });

    var LayoutView = Marionette.LayoutView.extend({
        tagName: "div",
        regions: {
            main: "#history-main",
            viewing: "#history-viewing",
            sheet: "#history-sheet"
        },

        register: function(model) {
            var self = this;
            var p = Parse.Promise.as([]);

            if (model != self.model) {
                self.model = model;
                self.picked = new Backbone.Model({value: 0});
                self.override = new Backbone.Model({character: null});

                p = self.model.get_recorded_changes().then(function () {
                    self.picked.set("value", self.model.recorded_changes.models.length - 1);

                    // Set up child views now
                    self.showChildView('main', new MainView({
                        model: self.model,
                        picked: self.picked,
                        override: self.override
                    }));
                    self.showChildView('viewing', new ViewingView({
                        model: self.model,
                        picked: self.picked
                    }));
                    var cpv = new CharacterPrintView;
                    cpv = cpv.setup(self.model, self.override);
                    self.showChildView('sheet', cpv);
                });
            }

            return p.then(function () {
                Parse.Promise.as(self);
            });
        },
        onRender: function () {
            this.$el.enhanceWithin();
        }
    });

    return LayoutView;

} );<|endoftext|>


<commit_before>var app = angular.module('testApp', ['ngMaterial']);
app.controller('MainController', function($scope, $mdSidenav) {
    $scope.openLeftMenu = function () {
        $mdSidenav('left').toggle();
    };
    $scope.openRightMenu = function () {
        $mdSidenav('right').toggle();
    };
    $scope.oriFeedback = {
        name: "",
        email: "",
        sendFeedback: ""
    };
    // Declare a variable called oriFeedback
    var oriFeedback = angular.copy($scope.oriFeedback);
    // On initial, set feedback to original
    $scope.feedback = angular.copy(oriFeedback);
    // Reset form
    $scope.reset = function () {
        $scope.feedback = angular.copy(oriFeedback);
        $scope.feedbackbeta.$setPristine();
    };
});

app.controller('SideNavController', function ($scope) {
    $scope.links = [
        {url: 'https://chan4077.github.io', icon: 'home', color_icon: 'black'},
        {url: 'https://chan4077.github.io/about', icon: 'account_box', color_icon: 'black'},
        {url: 'https://chan4077.github.io/blog', icon: '', color_icon: 'black'},
        {url: 'https://chan4077.github.io/media', icon: 'group', color_icon: 'black'},
        {url: 'https://chan4077.github.io/notes', icon: 'insert_drive_file', color_icon: 'black'},
        {url: 'https://chan4077.github.io/preferences', icon: 'settings', color_icon: 'black'},
        {url: 'https://chan4077.github.io/angular', icon: '', color_icon: 'black'}
    ]
});<commit_msg>:checkered_flag:Add $setUntouched()<commit_after>var app = angular.module('testApp', ['ngMaterial']);
app.controller('MainController', function($scope, $mdSidenav) {
    $scope.openLeftMenu = function () {
        $mdSidenav('left').toggle();
    };
    $scope.openRightMenu = function () {
        $mdSidenav('right').toggle();
    };
    $scope.oriFeedback = {
        name: "",
        email: "",
        sendFeedback: ""
    };
    // Declare a variable called oriFeedback
    var oriFeedback = angular.copy($scope.oriFeedback);
    // On initial, set feedback to original
    $scope.feedback = angular.copy(oriFeedback);
    // Reset form
    $scope.reset = function () {
        $scope.feedback = angular.copy(oriFeedback);
        // Reset form
        $scope.feedbackbeta.$setPristine();
        // Reset validation errors
        $scope.feedbackbeta.$setUntouched();
    };
});

app.controller('SideNavController', function ($scope) {
    $scope.links = [
        {url: 'https://chan4077.github.io', icon: 'home', color_icon: 'black'},
        {url: 'https://chan4077.github.io/about', icon: 'account_box', color_icon: 'black'},
        {url: 'https://chan4077.github.io/blog', icon: '', color_icon: 'black'},
        {url: 'https://chan4077.github.io/media', icon: 'group', color_icon: 'black'},
        {url: 'https://chan4077.github.io/notes', icon: 'insert_drive_file', color_icon: 'black'},
        {url: 'https://chan4077.github.io/preferences', icon: 'settings', color_icon: 'black'},
        {url: 'https://chan4077.github.io/angular', icon: '', color_icon: 'black'}
    ]
});<|endoftext|>