<commit_before>angular.module('app', ['ngCookies'])
    .controller('overwatchDataController', ['$cookies', '$cookieStore', '$scope','$http', function($cookies,$cookieStore,$scope,$http) {

        $scope.playerCount = 0;

        $scope.team = {
            'players': []
        };
        $scope.savedPlayers = $cookies.getObject("savedPlayers");

        $scope.showSuggested = false;

        $scope.compositions = [];   //[arco-1341, cRc-1211, ...]
        $scope.suggestedComp;
        $scope.roles = [];          //[tank, tank, dps, ...]
        $scope.tankCount = 2;
        $scope.dpsCount = 2;
        $scope.supportCount = 2;

        $scope.loading = false;
        $scope.loadingCount = 0;
        function loadingOn() {
            $scope.loadingCount += 1;
            $scope.loading=true
            console.log($scope.loadingCount);
        }
        function loadingOff() {
            $scope.loadingCount -= 1;
            if ($scope.loadingCount==0) {
                $scope.loading=false
            }
            console.log($scope.loadingCount);
        }

        $scope.add6Players = function() {
            $scope.addPlayer("arco#1341");
            $scope.addPlayer("cRc#1211");
            $scope.addPlayer("Murdock#11667");
            $scope.addPlayer("CrotalusX#1265");
            $scope.addPlayer("Dragnier#1375");
            $scope.addPlayer("Hexcyclone#1148");
        }

        $scope.removePlayer = function(battleTag) {
            for (player in $scope.team.players) {
                if ($scope.team.players[player].battleTag==battleTag) {
                    delete $scope.team.players[player];
                    $scope.team.players = $scope.team.players.filter(function (item) { return item != undefined });
                    $scope.playerCount -= 1;
                    return;
                }
            }
        }

        $scope.addPlayer = function(battleTag) {
            loadingOn();
            // get api data
            $http({
                method: 'GET',
                url: "https://owapi.net/api/v3/u/"+battleTag.replace("#", "-")+"/heroes"
            }).then(function successCallback(response) {
                // this callback will be called asynchronously
                // when the response is available

                // error if team already has 6 players
                if ($scope.playerCount == 6) {
                    loadingOff();
                    alert("6 players already on team");
                    return;
                }
                // get hero data; error if none
                let heroes = {};
                if (response.data.eu) {
                    heroes = response.data.eu.heroes;
                } else if (response.data.kr) {
                    heroes = response.data.kr.heroes;
                } else if (response.data.us) {
                    heroes = response.data.us.heroes;
                } else {
                    loadingOff();
                    alert("no such player found ["+battleTag+"]");
                    return;
                }

                // check if player already on team
                for (player in $scope.team.players) {
                    if ($scope.team.players[player].battleTag==battleTag) {
                        loadingOff();
                        alert("player ["+battleTag+"] already on team");
                        return;
                    }
                }

                for (player in $scope.savedPlayers) {
                    if ($scope.savedPlayers[player]==battleTag) {
                        break;
                    }
                    // save player for easy reuse
                    var now = new Date(), exp = new Date(now.getFullYear()+10, now.getMonth(), now.getDate());
                    if ($scope.savedPlayers == null) {
                        $scope.savedPlayers = [];
                    }
                    $scope.savedPlayers.push(battleTag);
                    $cookies.putObject("savedPlayers", $scope.savedPlayers, {'expires': exp});
                }

                console.log($cookies.getAll());

                // get all heroes (with win percentages) played more than two hours
                var heroesSortedByWin = [];
                for (hero in heroes.playtime.competitive) {
                    if (heroes.playtime.competitive[hero] >= 2) {
                        for (heroStats in heroes.stats.competitive) {
                            if (hero==heroStats) {
                                heroesSortedByWin.push({"name":hero, "win_percentage":(heroes.stats.competitive[hero].general_stats.win_percentage).slice(0,-1), "color":getColor(1-(heroes.stats.competitive[hero].general_stats.win_percentage).slice(0,-1)/100)});
                            }
                        }
                    }
                }
                // alert if player has no heroes with >= 2 hours
                if (heroesSortedByWin.length == 0) {
                    alert("player has no heros with >2 hours play time");
                }
                // sort array
                heroesSortedByWin.sort(function(a, b) {
                    return parseFloat(b.win_percentage) - parseFloat(a.win_percentage);
                });

                // get top 3
                //heroesSortedByWin = heroesSortedByWin.slice(0,3);

                // push to scope
                $scope.playerCount++;
                var player = {};
                player[battleTag]=heroesSortedByWin;
                $scope.team.players.push({name: battleTag.substring(0, battleTag.lastIndexOf("#")), battleTag:battleTag, heroes:heroesSortedByWin});
                // if 6 players on team, generate team comps
                if ($scope.playerCount == 6) {
                    $scope.genTeamComp();
                }
                loadingOff();
            }, function errorCallback(response) {
                // called asynchronously if an error occurs
                // or server returns response with an error status.
                //FIXME: get failed error code / remove. line below is for add6 testing function
                loadingOff();
                $scope.addPlayer(battleTag);
            });

        };

        // populates scope.roles with requested role selection
        var genRolesArray = function () {
            $scope.roles = [];
            var i;
            for (i = 0; i < $scope.tankCount; i++) {
                $scope.roles.push("tank");
            }
            for (i = 0; i < $scope.dpsCount; i++) {
                $scope.roles.push("dps");
            }
            for (i = 0; i < $scope.supportCount; i++) {
                $scope.roles.push("support");
            }
        }

        var permutator = function(inputArr) {
            var results = [];
            function permute(arr, memo) {
                var cur, memo = memo || [];
                for (var i = 0; i < arr.length; i++) {
                    cur = arr.splice(i, 1);
                    if (arr.length === 0) {
                        results.push(memo.concat(cur));
                    }
                    permute(arr.slice(), memo.concat(cur));
                    arr.splice(i, 0, cur[0]);
                }
                return results;
            }
            return permute(inputArr);
        }

        var genPlayersBestHeroForRole = function (player, role, used) {
            for (hero in player.heroes) {
                let r = genRole(player.heroes[hero].name);
                if (role==r.role && used.indexOf(player.heroes[hero].name)==-1) {
                    return {name:player.heroes[hero].name, win_percentage:player.heroes[hero].win_percentage};
                }
            }
            return {name:"n/a", win_percentage:0};
        }

        //$scope.genTC = function() { genTeamComp(); }

        $scope.genTeamComp = function () {
            loadingOn();
            $scope.compositions = [];
            genRolesArray();
            let playerPermutations = permutator($scope.team.players);
            let rolePermutations = permutator($scope.roles);
            for (playerCombo in playerPermutations) {
                for (roleCombo in rolePermutations) {
                    var comp = {};
                    var used = [];
                    comp.team = [];
                    var score = 0;
                    var i;
                    for (i=0; i<6; i++) {
                        let hero = genPlayersBestHeroForRole(playerPermutations[playerCombo][i], rolePermutations[roleCombo][i], used);
                        used.push(hero.name);
                        score = parseFloat(score) + parseFloat(hero.win_percentage);
                        comp.team.push({player:playerPermutations[playerCombo][i].name, hero:hero.name});
                    }
                    comp.score = score;
                    $scope.compositions.push(comp);
                }
            }
            $scope.compositions.sort(function(a, b) {
                return parseFloat(b.score) - parseFloat(a.score);
            });
            console.log($scope.compositions[0]);
            $scope.suggestedComp = $scope.compositions[0];
            $scope.showSuggested = true;
            loadingOff();
        }

        var getColor = function (value){
            //value from 0 to 1
            var hue=((1-value)*120).toString(10);
            return ["hsl(",hue,",100%,50%)"].join("");
        }

        var genRole = function(character) {
            switch(character) {
                case "ana":
                case "lucio":
                case "mercy":
                case "symmetra":
                case "zenyatta":
                    return {"role":"support", "special":"n/a"};
                    break;
                case "genji":
                case "hanzo":
                case "reaper":
                case "tracer":
                    return {"role":"dps", "special":"flanker"};
                    break;
                case "mei":
                case "torbjorn":
                    return {"role":"dps", "special":"off-tank"};
                    break;
                case "mccree":
                case "soldier76":
                case "widowmaker":
                    return {"role":"dps", "special":"hitscan"};
                    break;
                case "junkrat":
                case "bastion":
                case "pharah":
                    return {"role":"dps", "special":"n/a"};
                    break;
                case "dva":
                case "reinhardt":
                case "roadhog":
                case "winston":
                case "zarya":
                    return {"role":"tank", "special":"n/a"};
                    break;
            }
        }

}]);
<commit_msg>cookie save for player readd<commit_after>angular.module('app', ['ngCookies'])
    .controller('overwatchDataController', ['$cookies', '$cookieStore', '$scope','$http', function($cookies,$cookieStore,$scope,$http) {

        $scope.playerCount = 0;

        $scope.team = {
            'players': []
        };
        $scope.savedPlayers = $cookies.getObject("savedPlayers");

        $scope.showSuggested = false;

        $scope.compositions = [];   //[arco-1341, cRc-1211, ...]
        $scope.suggestedComp;
        $scope.roles = [];          //[tank, tank, dps, ...]
        $scope.tankCount = 2;
        $scope.dpsCount = 2;
        $scope.supportCount = 2;

        $scope.loading = false;
        $scope.loadingCount = 0;
        function loadingOn() {
            $scope.loadingCount += 1;
            $scope.loading=true
            console.log($scope.loadingCount);
        }
        function loadingOff() {
            $scope.loadingCount -= 1;
            if ($scope.loadingCount==0) {
                $scope.loading=false
            }
            console.log($scope.loadingCount);
        }

        $scope.add6Players = function() {
            $scope.addPlayer("arco#1341");
            $scope.addPlayer("cRc#1211");
            $scope.addPlayer("Murdock#11667");
            $scope.addPlayer("CrotalusX#1265");
            $scope.addPlayer("Dragnier#1375");
            $scope.addPlayer("Hexcyclone#1148");
        }

        $scope.removePlayer = function(battleTag) {
            for (player in $scope.team.players) {
                if ($scope.team.players[player].battleTag==battleTag) {
                    delete $scope.team.players[player];
                    $scope.team.players = $scope.team.players.filter(function (item) { return item != undefined });
                    $scope.playerCount -= 1;
                    return;
                }
            }
        }

        $scope.addPlayer = function(battleTag) {
            loadingOn();
            // get api data
            $http({
                method: 'GET',
                url: "https://owapi.net/api/v3/u/"+battleTag.replace("#", "-")+"/heroes"
            }).then(function successCallback(response) {
                // this callback will be called asynchronously
                // when the response is available

                // error if team already has 6 players
                if ($scope.playerCount == 6) {
                    loadingOff();
                    alert("6 players already on team");
                    return;
                }
                // get hero data; error if none
                let heroes = {};
                if (response.data.eu) {
                    heroes = response.data.eu.heroes;
                } else if (response.data.kr) {
                    heroes = response.data.kr.heroes;
                } else if (response.data.us) {
                    heroes = response.data.us.heroes;
                } else {
                    loadingOff();
                    alert("no such player found ["+battleTag+"]");
                    return;
                }

                // check if player already on team
                for (player in $scope.team.players) {
                    if ($scope.team.players[player].battleTag==battleTag) {
                        loadingOff();
                        alert("player ["+battleTag+"] already on team");
                        return;
                    }
                }

                for (player in $scope.savedPlayers) {
                    consol.log(player+"  "+$scope.savedPlayers[player])
                    if ($scope.savedPlayers[player]==battleTag) {
                        alert("foo");
                        break;
                    }
                    // save player for easy reuse
                    var now = new Date(), exp = new Date(now.getFullYear()+10, now.getMonth(), now.getDate());
                    if ($scope.savedPlayers == null) {
                        $scope.savedPlayers = [];
                    }
                    $scope.savedPlayers.push(battleTag);
                    $cookies.putObject("savedPlayers", $scope.savedPlayers, {'expires': exp});
                }

                console.log($cookies.getAll());

                // get all heroes (with win percentages) played more than two hours
                var heroesSortedByWin = [];
                for (hero in heroes.playtime.competitive) {
                    if (heroes.playtime.competitive[hero] >= 2) {
                        for (heroStats in heroes.stats.competitive) {
                            if (hero==heroStats) {
                                heroesSortedByWin.push({"name":hero, "win_percentage":(heroes.stats.competitive[hero].general_stats.win_percentage).slice(0,-1), "color":getColor(1-(heroes.stats.competitive[hero].general_stats.win_percentage).slice(0,-1)/100)});
                            }
                        }
                    }
                }
                // alert if player has no heroes with >= 2 hours
                if (heroesSortedByWin.length == 0) {
                    alert("player has no heros with >2 hours play time");
                }
                // sort array
                heroesSortedByWin.sort(function(a, b) {
                    return parseFloat(b.win_percentage) - parseFloat(a.win_percentage);
                });

                // get top 3
                //heroesSortedByWin = heroesSortedByWin.slice(0,3);

                // push to scope
                $scope.playerCount++;
                var player = {};
                player[battleTag]=heroesSortedByWin;
                $scope.team.players.push({name: battleTag.substring(0, battleTag.lastIndexOf("#")), battleTag:battleTag, heroes:heroesSortedByWin});
                // if 6 players on team, generate team comps
                if ($scope.playerCount == 6) {
                    $scope.genTeamComp();
                }
                loadingOff();
            }, function errorCallback(response) {
                // called asynchronously if an error occurs
                // or server returns response with an error status.
                //FIXME: get failed error code / remove. line below is for add6 testing function
                loadingOff();
                $scope.addPlayer(battleTag);
            });

        };

        // populates scope.roles with requested role selection
        var genRolesArray = function () {
            $scope.roles = [];
            var i;
            for (i = 0; i < $scope.tankCount; i++) {
                $scope.roles.push("tank");
            }
            for (i = 0; i < $scope.dpsCount; i++) {
                $scope.roles.push("dps");
            }
            for (i = 0; i < $scope.supportCount; i++) {
                $scope.roles.push("support");
            }
        }

        var permutator = function(inputArr) {
            var results = [];
            function permute(arr, memo) {
                var cur, memo = memo || [];
                for (var i = 0; i < arr.length; i++) {
                    cur = arr.splice(i, 1);
                    if (arr.length === 0) {
                        results.push(memo.concat(cur));
                    }
                    permute(arr.slice(), memo.concat(cur));
                    arr.splice(i, 0, cur[0]);
                }
                return results;
            }
            return permute(inputArr);
        }

        var genPlayersBestHeroForRole = function (player, role, used) {
            for (hero in player.heroes) {
                let r = genRole(player.heroes[hero].name);
                if (role==r.role && used.indexOf(player.heroes[hero].name)==-1) {
                    return {name:player.heroes[hero].name, win_percentage:player.heroes[hero].win_percentage};
                }
            }
            return {name:"n/a", win_percentage:0};
        }

        //$scope.genTC = function() { genTeamComp(); }

        $scope.genTeamComp = function () {
            loadingOn();
            $scope.compositions = [];
            genRolesArray();
            let playerPermutations = permutator($scope.team.players);
            let rolePermutations = permutator($scope.roles);
            for (playerCombo in playerPermutations) {
                for (roleCombo in rolePermutations) {
                    var comp = {};
                    var used = [];
                    comp.team = [];
                    var score = 0;
                    var i;
                    for (i=0; i<6; i++) {
                        let hero = genPlayersBestHeroForRole(playerPermutations[playerCombo][i], rolePermutations[roleCombo][i], used);
                        used.push(hero.name);
                        score = parseFloat(score) + parseFloat(hero.win_percentage);
                        comp.team.push({player:playerPermutations[playerCombo][i].name, hero:hero.name});
                    }
                    comp.score = score;
                    $scope.compositions.push(comp);
                }
            }
            $scope.compositions.sort(function(a, b) {
                return parseFloat(b.score) - parseFloat(a.score);
            });
            console.log($scope.compositions[0]);
            $scope.suggestedComp = $scope.compositions[0];
            $scope.showSuggested = true;
            loadingOff();
        }

        var getColor = function (value){
            //value from 0 to 1
            var hue=((1-value)*120).toString(10);
            return ["hsl(",hue,",100%,50%)"].join("");
        }

        var genRole = function(character) {
            switch(character) {
                case "ana":
                case "lucio":
                case "mercy":
                case "symmetra":
                case "zenyatta":
                    return {"role":"support", "special":"n/a"};
                    break;
                case "genji":
                case "hanzo":
                case "reaper":
                case "tracer":
                    return {"role":"dps", "special":"flanker"};
                    break;
                case "mei":
                case "torbjorn":
                    return {"role":"dps", "special":"off-tank"};
                    break;
                case "mccree":
                case "soldier76":
                case "widowmaker":
                    return {"role":"dps", "special":"hitscan"};
                    break;
                case "junkrat":
                case "bastion":
                case "pharah":
                    return {"role":"dps", "special":"n/a"};
                    break;
                case "dva":
                case "reinhardt":
                case "roadhog":
                case "winston":
                case "zarya":
                    return {"role":"tank", "special":"n/a"};
                    break;
            }
        }

}]);
<|endoftext|>


<commit_before>'use strict';

var app = angular.module('playApp', [
  'ngRoute',
  'playApp.units',
  'playApp.address',
  'playApp.hdkeys',
  'playApp.transaction',
  'playApp.unspent',
  'playApp.multisig'
]);

// Config
app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/units'});
}]);

app.constant('bitcore', require('bitcore-lib'));

// Filters
app.filter('btc', function(bitcore) {
  return function(satoshis) {
    return bitcore.Unit.fromSatoshis(satoshis).toBTC();
  };
})
.filter('permalink', function(bitcore) {
  return function(data, section) {
    var url = './#/' + section + '?data=' + encodeURI(data);
    if (url.length > 2083) throw new Error('URL too long')
    return url;
  };
})
.filter('ellipsify', function() {
  return function(data) {
    return data.substr(0, 4) + '...' + data.substr(data.length - 4, data.length);
  };
});

// Directives
app.directive('exampleCode', function() {
  return {
    link: function(scope, element, attrs) {
      scope.$watch(attrs.exampleCode, function(value) {
        element.text(value);
        hljs.highlightBlock(element[0]);
      });
    }
  };
})
.directive('autoSelect', function() {
  return {
    link: function(scope, element, attrs) {
      $(element).focus(function(){
        $(this).select();
      });
      element.attr('spellcheck', false);
    }
  };
})
.directive('requireTooltip', function() {
  return {
    link: function(scope, element, attrs) {
     $(document).foundation();
     $(document).foundation('tooltip', 'reflow');
    }
  };
})
.directive('requireModal', function() {
  return {
    link: function(scope, element, attrs) {
     $(document).foundation();
     $(document).foundation('reveal', 'reflow');
    }
  };
});

// Filters
function registerValidator(app, name, validator) {
  app.directive(name, function(bitcore) {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        function validate(value) {
          var valid = validator(bitcore, value, scope, attr);
          ngModel.$setValidity(null, valid);
          return value;
        }
        ngModel.$parsers.unshift(validate);
        ngModel.$formatters.unshift(validate);
      }
    };
  });
}

registerValidator(app, 'privateKey', function(bitcore, value) {
  return bitcore.PrivateKey.isValid(value);
});
registerValidator(app, 'publicKey', function(bitcore, value) {
  return bitcore.PublicKey.isValid(value);
});
registerValidator(app, 'xprivateKey', function(bitcore, value) {
  return bitcore.HDPrivateKey.isValidSerialized(value);
});
registerValidator(app, 'xpublicKey', function(bitcore, value) {
  return bitcore.HDPublicKey.isValidSerialized(value);
});
registerValidator(app, 'privateHdpath', function(bitcore, value, scope) {
  return !!(/^[mM][']?(\/[0-9]+[']?)*[/]?$/.exec(value));
});
registerValidator(app, 'publicHdpath', function(bitcore, value, scope) {
  return !!(/^[mM](\/[0-9]+)*[/]?$/.exec(value));
});
registerValidator(app, 'address', function(bitcore, value) {
  return bitcore.Address.isValid(value);
});

// Sidebar
app.controller('SideBar', function($scope, $rootScope, $timeout, $location) {
  $timeout(function(){
    $rootScope.showFooter = true;
    $rootScope.$apply();
  }, 100);

  $scope.getClass = function(path) {
    return $location.path().substr(0, path.length) === path ? "current" : "";
  }

})
.controller('Network', function($scope, $rootScope, $timeout, bitcore) {
  var networks = bitcore.Networks;
  networks.defaultNetwork = networks.testnet;
  $rootScope.$broadcast('networkUpdate');

  $scope.setTestnet = function(value) {
    networks.defaultNetwork = value ? networks.livenet : networks.testnet;
    $rootScope.$broadcast('networkUpdate');
  };
});
<commit_msg>require bitcore-lib-dash<commit_after>'use strict';

var app = angular.module('playApp', [
  'ngRoute',
  'playApp.units',
  'playApp.address',
  'playApp.hdkeys',
  'playApp.transaction',
  'playApp.unspent',
  'playApp.multisig'
]);

// Config
app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/units'});
}]);

app.constant('bitcore', require('bitcore-lib-dash'));

// Filters
app.filter('btc', function(bitcore) {
  return function(satoshis) {
    return bitcore.Unit.fromSatoshis(satoshis).toBTC();
  };
})
.filter('permalink', function(bitcore) {
  return function(data, section) {
    var url = './#/' + section + '?data=' + encodeURI(data);
    if (url.length > 2083) throw new Error('URL too long')
    return url;
  };
})
.filter('ellipsify', function() {
  return function(data) {
    return data.substr(0, 4) + '...' + data.substr(data.length - 4, data.length);
  };
});

// Directives
app.directive('exampleCode', function() {
  return {
    link: function(scope, element, attrs) {
      scope.$watch(attrs.exampleCode, function(value) {
        element.text(value);
        hljs.highlightBlock(element[0]);
      });
    }
  };
})
.directive('autoSelect', function() {
  return {
    link: function(scope, element, attrs) {
      $(element).focus(function(){
        $(this).select();
      });
      element.attr('spellcheck', false);
    }
  };
})
.directive('requireTooltip', function() {
  return {
    link: function(scope, element, attrs) {
     $(document).foundation();
     $(document).foundation('tooltip', 'reflow');
    }
  };
})
.directive('requireModal', function() {
  return {
    link: function(scope, element, attrs) {
     $(document).foundation();
     $(document).foundation('reveal', 'reflow');
    }
  };
});

// Filters
function registerValidator(app, name, validator) {
  app.directive(name, function(bitcore) {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        function validate(value) {
          var valid = validator(bitcore, value, scope, attr);
          ngModel.$setValidity(null, valid);
          return value;
        }
        ngModel.$parsers.unshift(validate);
        ngModel.$formatters.unshift(validate);
      }
    };
  });
}

registerValidator(app, 'privateKey', function(bitcore, value) {
  return bitcore.PrivateKey.isValid(value);
});
registerValidator(app, 'publicKey', function(bitcore, value) {
  return bitcore.PublicKey.isValid(value);
});
registerValidator(app, 'xprivateKey', function(bitcore, value) {
  return bitcore.HDPrivateKey.isValidSerialized(value);
});
registerValidator(app, 'xpublicKey', function(bitcore, value) {
  return bitcore.HDPublicKey.isValidSerialized(value);
});
registerValidator(app, 'privateHdpath', function(bitcore, value, scope) {
  return !!(/^[mM][']?(\/[0-9]+[']?)*[/]?$/.exec(value));
});
registerValidator(app, 'publicHdpath', function(bitcore, value, scope) {
  return !!(/^[mM](\/[0-9]+)*[/]?$/.exec(value));
});
registerValidator(app, 'address', function(bitcore, value) {
  return bitcore.Address.isValid(value);
});

// Sidebar
app.controller('SideBar', function($scope, $rootScope, $timeout, $location) {
  $timeout(function(){
    $rootScope.showFooter = true;
    $rootScope.$apply();
  }, 100);

  $scope.getClass = function(path) {
    return $location.path().substr(0, path.length) === path ? "current" : "";
  }

})
.controller('Network', function($scope, $rootScope, $timeout, bitcore) {
  var networks = bitcore.Networks;
  networks.defaultNetwork = networks.testnet;
  $rootScope.$broadcast('networkUpdate');

  $scope.setTestnet = function(value) {
    networks.defaultNetwork = value ? networks.livenet : networks.testnet;
    $rootScope.$broadcast('networkUpdate');
  };
});
<|endoftext|>


<commit_before>var DirectoryPosts = _Config.post.DirectoryPosts || "posts";

function getPosts(noreverse) {
	var data = [];
	if (noreverse) {
		var posts = _fs.readdirSync(DirectoryPosts);
	} else {
		var posts = _fs.readdirSync(DirectoryPosts).reverse();
	}

	for (var i = 0; i < posts.length; i++) {
		if (_fs.existsSync(DirectoryPosts + '/' + posts[i] + ".asc")) {
			data.push(posts[i].replace(".html", ''));
		}
	}

	return data;
}

function getPost(id) {
	if (_fs.existsSync(DirectoryPosts + '/' + id + ".html.asc")) {
		return _fs.readFileSync(DirectoryPosts + '/' + id + '.html', 'utf8');
	} else {
		return '';
	}
}

function getPage(content) {
	var header = _fs.readFileSync((_Config.post.FileHeader || "header.html"), 'utf8');
	var footer = _fs.readFileSync((_Config.post.FileFooter || "footer.html"), 'utf8');
	return header + content + footer;
}

exports.getPost = getPost;
exports.getPosts = getPosts;
exports.getPage = getPage;
<commit_msg>add write post function<commit_after>var DirectoryPosts = _Config.post.DirectoryPosts || "posts";

function getPosts(noreverse) {
	var data = [];
	if (noreverse) {
		var posts = _fs.readdirSync(DirectoryPosts);
	} else {
		var posts = _fs.readdirSync(DirectoryPosts).reverse();
	}

	for (var i = 0; i < posts.length; i++) {
		if (_fs.existsSync(DirectoryPosts + '/' + posts[i] + ".asc")) {
			data.push(posts[i].replace(".html", ''));
		}
	}

	return data;
}

function writePost(id, content) {
	_fs.writeFileSync(DirectoryPosts + '/' + id + ".html", content, 'utf8');
	_fs.writeFileSync(DirectoryPosts + '/' + id + ".html.asc", '', 'utf8');
}

function getPost(id) {
	if (_fs.existsSync(DirectoryPosts + '/' + id + ".html.asc")) {
		return _fs.readFileSync(DirectoryPosts + '/' + id + '.html', 'utf8');
	} else {
		return '';
	}
}

function getPage(content) {
	var header = _fs.readFileSync((_Config.post.FileHeader || "header.html"), 'utf8');
	var footer = _fs.readFileSync((_Config.post.FileFooter || "footer.html"), 'utf8');
	return header + content + footer;
}

exports.getPost = getPost;
exports.getPosts = getPosts;
exports.getPage = getPage;
exports.writePost = writePost;
<|endoftext|>


<commit_before>/**
 * jQuery Dynamic ImageMap v0.1.0
 *
 * A jQuery plugin to create dynamic elements to be placed over area tags coordinates in image map
 *
 * @author      Justin John Mathews <justin.johnmathews@gmail.com>
 * @copyright   (c) 2016 Justin John Mathews
 * @license     MIT
 */
(function($) {
    /**
     * The method for creating custom elements dynamically for all area tags in image map
     * that will be placed on top of image where area coordinates defines.
     *
     * @param {Object} options
     * @return {Object|this}
     */
    $.fn.dynamicImageMap = function(options) {
        options || (options = {});

        var mapElement, coords, parent,
            areas = options.areas,
            image = this;

        /* If area and maps objects are not found in options, check corresponding image usemap attribute to find map element */
        if (!options.areas && !options.maps) {
			try {
				areas = $('map[name=' + image.attr("usemap").replace(/^#/, '') + '] area');
			} catch(e) {
				throw new Error('The image tag("' + image.selector + '") is missing the usemap attribute');
			}
        }

        /* Wrap image with div tag for creating dynamically created anchor elements positioned in it. */
        image.wrap($("<div>", {
            class: $(image).data('class') || '',
            style: $(image).data('style') || ''
        }));

        parent = image.parent();

        parent.css({
            position: 'relative',
            display: 'inline-block'
        });

		var setMapElemStyle = function(mapElement, coords) {
			mapElement.css('position', 'absolute');

			/* Split coordinates to array for anchor elements styling */
			coords = coords.split(',');

			switch (coords.length) {
				/* CIRCLE */
				case 3:
					mapElement.css({
						borderRadius: coords[2] * 1,
						top: coords[1] - coords[2],
						left: coords[0] - coords[2],
						width: coords[2] * 2,
						height: coords[2] * 2
					});
					break;

				/* RECT */
				case 4:
					mapElement.css({
						top: coords[1] * 1,
						left: coords[0] * 1,
						width: coords[2] - coords[0],
						height: coords[3] - coords[1]
					});
					break;
				default:
					mapElement = null;
					break;
			}

			return mapElement;
		}

		if (areas) {
			/* Iterate through all area tags in map tag to create corresponding dynamic element in the image */
			areas.map(function(i, n) {
				mapElement = $("<a>", {
					class: $(n).data('class') || '',
					style: $(n).data('style') || '',
					html: $(n).data('content') || '',
					href: $(n).attr('href') || '#'
				});
				mapElement = setMapElemStyle(mapElement, n.coords);
				parent.append(mapElement);
			});
		} else {
			/* Iterate through maps array in options object.
			 * This will create dynamic elements which resembles to map elements for image tag
			 * and corresponding image tag doesn't have associated map element
			 */
			options.maps.forEach(function (n, i) {
				mapElement = $("<a>", {
					class: n.classes || '',
					style: n.style || '',
					html: n.content || '',
					href: n.href || '#'
				});
				mapElement = setMapElemStyle(mapElement, n.coords);
				parent.append(mapElement);
			});
		}
        return this;
    };

}(window.jQuery));<commit_msg>Update comments<commit_after>/**
 * jQuery Dynamic ImageMap v0.1.0
 *
 * A jQuery plugin to create dynamic elements to be placed over area tags coordinates in image map
 *
 * @author      Justin John Mathews <justinjohnmathews@gmail.com>
 * @copyright   (c) 2016 Justin John Mathews
 * @license     MIT
 */
(function($) {
    /**
     * The method for creating custom elements dynamically for all area tags in image map
     * that will be placed on top of image where area coordinates defines.
     *
     * @param {Object} options
     * @return {Object|this}
     */
    $.fn.dynamicImageMap = function(options) {
        options || (options = {});

        var mapElement, coords, parent,
            areas = options.areas,
            image = this;

        /* If area and maps objects are not found in options, check corresponding image usemap attribute to find map element */
        if (!options.areas && !options.maps) {
			try {
				areas = $('map[name=' + image.attr("usemap").replace(/^#/, '') + '] area');
			} catch(e) {
				throw new Error('The image tag("' + image.selector + '") is missing the usemap attribute');
			}
        }

        /* Wrap image with div tag for creating dynamically created anchor elements positioned in it. */
        image.wrap($("<div>", {
            class: $(image).data('class') || '',
            style: $(image).data('style') || ''
        }));

        parent = image.parent();

        parent.css({
            position: 'relative',
            display: 'inline-block'
        });

		var setMapElemStyle = function(mapElement, coords) {
			mapElement.css('position', 'absolute');

			/* Split coordinates to array for anchor elements styling */
			coords = coords.split(',');

			switch (coords.length) {
				/* CIRCLE */
				case 3:
					mapElement.css({
						borderRadius: coords[2] * 1,
						top: coords[1] - coords[2],
						left: coords[0] - coords[2],
						width: coords[2] * 2,
						height: coords[2] * 2
					});
					break;

				/* RECT */
				case 4:
					mapElement.css({
						top: coords[1] * 1,
						left: coords[0] * 1,
						width: coords[2] - coords[0],
						height: coords[3] - coords[1]
					});
					break;
				default:
					mapElement = null;
					break;
			}

			return mapElement;
		}

		if (areas) {
			/* Iterate through all area tags in map tag to create corresponding dynamic element in the image */
			areas.map(function(i, n) {
				mapElement = $("<a>", {
					class: $(n).data('class') || '',
					style: $(n).data('style') || '',
					html: $(n).data('content') || '',
					href: $(n).attr('href') || '#'
				});
				mapElement = setMapElemStyle(mapElement, n.coords);
				parent.append(mapElement);
			});
		} else {
			/* Iterate through maps array in options object.
			 * This will create dynamic elements which resembles to map elements for image tag
			 * and corresponding image tag doesn't have associated map element
			 */
			options.maps.forEach(function (n, i) {
				mapElement = $("<a>", {
					class: n.classes || '',
					style: n.style || '',
					html: n.content || '',
					href: n.href || '#'
				});
				mapElement = setMapElemStyle(mapElement, n.coords);
				parent.append(mapElement);
			});
		}
        return this;
    };

}(window.jQuery));<|endoftext|>


<commit_before>import React from "react";
import CX from "classnames";
import PropTypes from "prop-types";
import { map, sortBy } from "lodash-es";
import { Badge, ListGroup } from "react-bootstrap";
import { connect } from "react-redux";

import { byteSize } from "../../utils";
import { hideUploadOverlay } from "../actions";
import { Flex, FlexItem, ListGroupItem, ProgressBar } from "../../base";

const UploadItem = ({ localId, name, progress, size}) => (
    <ListGroupItem key={localId} disabled={progress === 0}>
        <ProgressBar bsStyle={progress === 100 ? "primary" : "success"} now={progress} affixed />
        <Flex>
            <FlexItem grow={1}>
                {name}
            </FlexItem>
            <FlexItem shrink={0} grow={0} pad={15}>
                {byteSize(size)}
            </FlexItem>
        </Flex>
    </ListGroupItem>
);

class UploadOverlay extends React.Component {

    componentWillReceiveProps (nextProps) {
        if (nextProps.uploadsComplete !== this.props.uploadsComplete && nextProps.uploadsComplete) {
            window.removeEventListener("beforeunload", this.handlePageLeave);
        } else if (nextProps.uploadsComplete !== this.props.uploadsComplete && !nextProps.uploadsComplete) {
            window.addEventListener("beforeunload", this.handlePageLeave);
        }
    }

    handlePageLeave (e) {
        const message = "Upload(s) still in progress";
        e.returnValue = message;
        return message;
    }

    render () {

        const classNames = CX("upload-overlay", {hidden: !this.props.showUploadOverlay});
        const uploadComponents = map(sortBy(this.props.uploads, "progress").reverse(), upload =>
            upload.progress === 100 ?
 : <UploadItem key={upload.localId} {...upload} />
        );

        let content = this.props.uploadsComplete ? null : (

                            Uploads <Badge>{uploadComponents.length}</Badge>

                        <button type="button" className="close pullRight" onClick={this.props.onClose}>
                            ×
                        </button>

                    <ListGroup style={{height: "auto", maxHeight: "175px", overflowX: "hidden"}}>
                        {uploadComponents}
                    </ListGroup>

        );

        return
{content}
;
    }
}

UploadOverlay.propTypes = {
    uploads: PropTypes.arrayOf(PropTypes.object),
    showUploadOverlay: PropTypes.bool,
    uploadsComplete: PropTypes.bool,
    onClose: PropTypes.func
};

const mapStateToProps = (state) => ({...state.files});

const mapDispatchToProps = (dispatch) => ({

    onClose: () => {
        dispatch(hideUploadOverlay());
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(UploadOverlay);

export default Container;
<commit_msg>Fix lint issues in UploadOverlay<commit_after>import React from "react";
import CX from "classnames";
import PropTypes from "prop-types";
import { map, sortBy } from "lodash-es";
import { Badge, ListGroup } from "react-bootstrap";
import { connect } from "react-redux";

import { byteSize } from "../../utils";
import { hideUploadOverlay } from "../actions";
import { Flex, FlexItem, ListGroupItem, ProgressBar } from "../../base";

const UploadItem = ({ localId, name, progress, size}) => (
    <ListGroupItem key={localId} disabled={progress === 0}>
        <ProgressBar bsStyle={progress === 100 ? "primary" : "success"} now={progress} affixed />
        <Flex>
            <FlexItem grow={1}>
                {name}
            </FlexItem>
            <FlexItem shrink={0} grow={0} pad={15}>
                {byteSize(size)}
            </FlexItem>
        </Flex>
    </ListGroupItem>
);

class UploadOverlay extends React.Component {

    componentWillReceiveProps (nextProps) {
        if (nextProps.uploadsComplete !== this.props.uploadsComplete && nextProps.uploadsComplete) {
            window.removeEventListener("beforeunload", this.handlePageLeave);
        } else if (nextProps.uploadsComplete !== this.props.uploadsComplete && !nextProps.uploadsComplete) {
            window.addEventListener("beforeunload", this.handlePageLeave);
        }
    }

    handlePageLeave = (e) => {
        const message = "Upload(s) still in progress";
        e.returnValue = message;
        return message;
    };

    render () {

        const classNames = CX("upload-overlay", {hidden: !this.props.showUploadOverlay});
        const uploadComponents = map(sortBy(this.props.uploads, "progress").reverse(), upload =>
            upload.progress === 100 ?
 : <UploadItem key={upload.localId} {...upload} />
        );

        if (this.props.uploadsComplete) {
            return
;
        }

        return (

                            Uploads <Badge>{uploadComponents.length}</Badge>

                        <button type="button" className="close pullRight" onClick={this.props.onClose}>
                            ×
                        </button>

                    <ListGroup style={{height: "auto", maxHeight: "175px", overflowX: "hidden"}}>
                        {uploadComponents}
                    </ListGroup>

        );
    }
}

UploadOverlay.propTypes = {
    uploads: PropTypes.arrayOf(PropTypes.object),
    showUploadOverlay: PropTypes.bool,
    uploadsComplete: PropTypes.bool,
    onClose: PropTypes.func
};

const mapStateToProps = (state) => ({...state.files});

const mapDispatchToProps = (dispatch) => ({

    onClose: () => {
        dispatch(hideUploadOverlay());
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(UploadOverlay);

export default Container;
<|endoftext|>


<commit_before>var gmap;
var geocoder;

var autofillNameEnabled;
var autofillMapEnabled;

var streetNumber = /\d+[a-z]*/;
// This format is used also in forms.py so keep it in sync
// We remove all those characters as we are constructing the name by appending the street number ourselves
var nodeName = /[^a-z]/g;

function mapInit(map) {
  gmap = map;
}

function mapEditInit(map) {
  mapInit(map);

  var lat = $('#id_geo_lat').val();
  var long = $('#id_geo_long').val();

  autofillMapEnabled = !lat && !long;
  autofillNameEnabled = !$('#id_name').val();

  if (lat && long) {
    lat = parseFloat(lat);
    long = parseFloat(long);
    if (isFinite(lat) && isFinite(long)) {
      var point = new google.maps.LatLng(lat, long);
      if (point) {
        putMarker(map, point);
        map.setCenter(point);
      }
    }
  }

  geocoder = new google.maps.ClientGeocoder();
  geocoder.setViewport(map.getBounds());
}

function mapClick(map, point) {
  autofillMapEnabled = false;
}

function toggleAutoConfiguration() {
  if ($('#id_wan_dhcp').is(':checked')) {
    $('.static_opts').css('display', 'none');
  }
  else {
    $('.static_opts').css('display', '');
  }
}

function toggleImageGeneratorOptions(dontToggleExtAntenna) {
  if ($('#id_template').attr('value') == '') {
    $('.imagegen_opts').css('display', 'none');
  }
  else {
    $('.imagegen_opts').css('display', '');
    toggleAutoConfiguration();
    toggleVpnOptions();
    if (!dontToggleExtAntenna) {
      toggleExtAntenna(true);
    }
  }
}

function toggleVpnOptions() {
  if ($('#id_use_vpn').is(':checked')) {
    $('.vpn_opts').css('display', '');
  }
  else {
    $('.vpn_opts').css('display', 'none');
  }
}

function toggleLocation() {
  if ($('#id_node_type').attr('value') == mobileNodeType) {
    $('.location_opts').css('display', 'none');
  }
  else {
    $('.location_opts').css('display', '');
  }
}

function toggleDead() {
  if ($('#id_node_type').attr('value') == deadNodeType) {
    $('.alive').css('display', 'none');
    $('#content :input').not('.dead_active :input').attr('disabled', 'disabled');
    clickEnabled = false;
  }
  else {
    $('.alive').css('display', '');
    $('#content :input').removeAttr('disabled');
    toggleIpInput();
    clickEnabled = true;
  }
}

function toggleExtAntenna(dontToggleImageGenerator) {
  if ($('#id_ant_external').is(':checked')) {
    $('.extantenna_opts').css('display', '');
    if (!dontToggleImageGenerator) {
      toggleImageGeneratorOptions(true);
    }
  }
  else {
    $('.extantenna_opts').css('display', 'none');
  }
}

function toggleIpInput() {
  if ($('#id_assign_ip').is(':checked')) {
    $('#id_ip').attr('value', '');
    $('#id_ip').attr('disabled', 'disabled');
  }
  else {
    $('#id_ip').removeAttr('disabled');
  }
}

function updateMapForProject() {
  if (nodeMarker) {
    // marker is already set so we will not move map
    return;
  }
  var projectId = $('#id_project').attr('value');
  if (projects[projectId]) {
    gmap.setCenter(new google.maps.LatLng(projects[projectId].lat, projects[projectId].long), projects[projectId].zoom);
    geocoder.setViewport(gmap.getBounds());
  }
}

function updatePoolsForProject() {
  if (!pools)
    return;

  var projectId = $('#id_project').attr('value');
  var pool = $('#id_pool');
  pool.empty();

  pool_list = pools[projectId]["list"];
  for (var i = 0; i < pool_list.length; i++) {
    pool.append('<option value="' + pool_list[i].id + '">' + pool_list[i].description + ' [' + pool_list[i].subnet + ']</option>');
  }

  pool.attr('value', pools[projectId]["default"]);
}

function updatePrefixLengthsForPool() {
  if (!pools)
    return;

  var projectId = $('#id_project').attr('value');
  var poolId = $('#id_pool').attr('value');
  var pool;
  pool_list = pools[projectId]["list"];
  for (var i = 0; i < pool_list.length; i++) {
    if (pool_list[i].id == poolId) {
      pool = pool_list[i];
      break;
    }
  }

  var prefs = $('#id_prefix_len');
  prefs.empty();
  for (var i = pool.min_prefix_len; i <= pool.max_prefix_len; i++) {
    prefs.append('<option value="' + i + '">/' + i + '</option>');
  }
  prefs.attr('value', '' + pool.def_prefix_len);
}

function generateRandomPassword(event) {
  event.preventDefault();
  var choices = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  var password = "";
  for (var i = 0; i < 8; i++) {
    password += choices.charAt(Math.floor(Math.random() * choices.length));
  }
  $('#id_root_pass').val(password);
  return false;
}

function fillMapLocation() {
  if (($('#id_geo_lat').val() || $('#id_geo_long').val()) && !autofillMapEnabled) {
    return;
  }
  autofillMapEnabled = true;

  geocoder.getLatLng(
    $('#id_location').val(),
    function (point) {
      if (autofillMapEnabled && point && gmap.getBounds().containsLatLng(point)) {
        putMarker(gmap, point);
      }
    }
  );
}

function fillName() {
  if ($('#id_name').val() && !autofillNameEnabled) {
    return;
  }
  autofillNameEnabled = true;

  var name = unidecode($('#id_location').val()).toLowerCase();
  number = name.match(streetNumber);
  name = name.replace(streetNumber, "");
  name = name.replace(nodeName, "");
  if (number) {
    name += "-" + number;
  }
  $('#id_name').val(name);
}

$(document).ready(function () {
  $('#id_project').change(function(event) {
    updateMapForProject();
    updatePoolsForProject();

    if ($('#id_prefix_len').length) {
      updatePrefixLengthsForPool();
    }
    return true;
  });
  $('#id_wan_dhcp').change(function(event) { toggleAutoConfiguration(); return true; });
  $('#id_template').change(function(event) { toggleImageGeneratorOptions(); return true; });
  $('#id_node_type').change(function(event) {
    toggleLocation();
    toggleDead();
    return true;
  });
  $('#id_ant_external').change(function(event) { toggleExtAntenna(); return true; });
  $('#id_use_vpn').change(function(event) { toggleVpnOptions(); return true; });

  $('#id_location').keyup(function(event) {
    fillMapLocation();
    fillName();
    return true;
  });
  $('#id_geo_lat').change(function(event) { autofillMapEnabled = false; return true; });
  $('#id_geo_long').change(function(event) { autofillMapEnabled = false; return true; });
  $('#id_name').change(function(event) { autofillNameEnabled = false; return true; })

  $('#id_root_pass').after(']').after($('<a />').attr('href', '#').text('generate new').click(generateRandomPassword)).after(' [');

  toggleAutoConfiguration();
  toggleVpnOptions();
  toggleImageGeneratorOptions();
  toggleLocation();
  toggleExtAntenna();
  updatePoolsForProject();
  toggleDead();

  if ($('#id_prefix_len').length) {
    $('#id_pool').change(function(event) {
      updatePrefixLengthsForPool();
      return true;
    });

    updatePrefixLengthsForPool();
  }
});
<commit_msg>Improved JavaScript random password generation. See #978<commit_after>var gmap;
var geocoder;

var autofillNameEnabled;
var autofillMapEnabled;

var streetNumber = /\d+[a-z]*/;
// This format is used also in forms.py so keep it in sync
// We remove all those characters as we are constructing the name by appending the street number ourselves
var nodeName = /[^a-z]/g;

function mapInit(map) {
  gmap = map;
}

function mapEditInit(map) {
  mapInit(map);

  var lat = $('#id_geo_lat').val();
  var long = $('#id_geo_long').val();

  autofillMapEnabled = !lat && !long;
  autofillNameEnabled = !$('#id_name').val();

  if (lat && long) {
    lat = parseFloat(lat);
    long = parseFloat(long);
    if (isFinite(lat) && isFinite(long)) {
      var point = new google.maps.LatLng(lat, long);
      if (point) {
        putMarker(map, point);
        map.setCenter(point);
      }
    }
  }

  geocoder = new google.maps.ClientGeocoder();
  geocoder.setViewport(map.getBounds());
}

function mapClick(map, point) {
  autofillMapEnabled = false;
}

function toggleAutoConfiguration() {
  if ($('#id_wan_dhcp').is(':checked')) {
    $('.static_opts').css('display', 'none');
  }
  else {
    $('.static_opts').css('display', '');
  }
}

function toggleImageGeneratorOptions(dontToggleExtAntenna) {
  if ($('#id_template').attr('value') == '') {
    $('.imagegen_opts').css('display', 'none');
  }
  else {
    $('.imagegen_opts').css('display', '');
    toggleAutoConfiguration();
    toggleVpnOptions();
    if (!dontToggleExtAntenna) {
      toggleExtAntenna(true);
    }
  }
}

function toggleVpnOptions() {
  if ($('#id_use_vpn').is(':checked')) {
    $('.vpn_opts').css('display', '');
  }
  else {
    $('.vpn_opts').css('display', 'none');
  }
}

function toggleLocation() {
  if ($('#id_node_type').attr('value') == mobileNodeType) {
    $('.location_opts').css('display', 'none');
  }
  else {
    $('.location_opts').css('display', '');
  }
}

function toggleDead() {
  if ($('#id_node_type').attr('value') == deadNodeType) {
    $('.alive').css('display', 'none');
    $('#content :input').not('.dead_active :input').attr('disabled', 'disabled');
    clickEnabled = false;
  }
  else {
    $('.alive').css('display', '');
    $('#content :input').removeAttr('disabled');
    toggleIpInput();
    clickEnabled = true;
  }
}

function toggleExtAntenna(dontToggleImageGenerator) {
  if ($('#id_ant_external').is(':checked')) {
    $('.extantenna_opts').css('display', '');
    if (!dontToggleImageGenerator) {
      toggleImageGeneratorOptions(true);
    }
  }
  else {
    $('.extantenna_opts').css('display', 'none');
  }
}

function toggleIpInput() {
  if ($('#id_assign_ip').is(':checked')) {
    $('#id_ip').attr('value', '');
    $('#id_ip').attr('disabled', 'disabled');
  }
  else {
    $('#id_ip').removeAttr('disabled');
  }
}

function updateMapForProject() {
  if (nodeMarker) {
    // marker is already set so we will not move map
    return;
  }
  var projectId = $('#id_project').attr('value');
  if (projects[projectId]) {
    gmap.setCenter(new google.maps.LatLng(projects[projectId].lat, projects[projectId].long), projects[projectId].zoom);
    geocoder.setViewport(gmap.getBounds());
  }
}

function updatePoolsForProject() {
  if (!pools)
    return;

  var projectId = $('#id_project').attr('value');
  var pool = $('#id_pool');
  pool.empty();

  pool_list = pools[projectId]["list"];
  for (var i = 0; i < pool_list.length; i++) {
    pool.append('<option value="' + pool_list[i].id + '">' + pool_list[i].description + ' [' + pool_list[i].subnet + ']</option>');
  }

  pool.attr('value', pools[projectId]["default"]);
}

function updatePrefixLengthsForPool() {
  if (!pools)
    return;

  var projectId = $('#id_project').attr('value');
  var poolId = $('#id_pool').attr('value');
  var pool;
  pool_list = pools[projectId]["list"];
  for (var i = 0; i < pool_list.length; i++) {
    if (pool_list[i].id == poolId) {
      pool = pool_list[i];
      break;
    }
  }

  var prefs = $('#id_prefix_len');
  prefs.empty();
  for (var i = pool.min_prefix_len; i <= pool.max_prefix_len; i++) {
    prefs.append('<option value="' + i + '">/' + i + '</option>');
  }
  prefs.attr('value', '' + pool.def_prefix_len);
}

function generateRandomPassword(event) {
  event.preventDefault();
  function random() {
    // Math.random is not random enough by default
    now = new Date();
    for (var i = now.getMilliseconds() % 100; i >= 0; i--) {
      Math.random();
    }
    return Math.random();
  }
  var choices = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  var password = "";
  for (var i = 0; i < 8; i++) {
    password += choices.charAt(Math.floor(random() * choices.length));
  }
  $('#id_root_pass').val(password);
  return false;
}

function fillMapLocation() {
  if (($('#id_geo_lat').val() || $('#id_geo_long').val()) && !autofillMapEnabled) {
    return;
  }
  autofillMapEnabled = true;

  geocoder.getLatLng(
    $('#id_location').val(),
    function (point) {
      if (autofillMapEnabled && point && gmap.getBounds().containsLatLng(point)) {
        putMarker(gmap, point);
      }
    }
  );
}

function fillName() {
  if ($('#id_name').val() && !autofillNameEnabled) {
    return;
  }
  autofillNameEnabled = true;

  var name = unidecode($('#id_location').val()).toLowerCase();
  number = name.match(streetNumber);
  name = name.replace(streetNumber, "");
  name = name.replace(nodeName, "");
  if (number) {
    name += "-" + number;
  }
  $('#id_name').val(name);
}

$(document).ready(function () {
  $('#id_project').change(function(event) {
    updateMapForProject();
    updatePoolsForProject();

    if ($('#id_prefix_len').length) {
      updatePrefixLengthsForPool();
    }
    return true;
  });
  $('#id_wan_dhcp').change(function(event) { toggleAutoConfiguration(); return true; });
  $('#id_template').change(function(event) { toggleImageGeneratorOptions(); return true; });
  $('#id_node_type').change(function(event) {
    toggleLocation();
    toggleDead();
    return true;
  });
  $('#id_ant_external').change(function(event) { toggleExtAntenna(); return true; });
  $('#id_use_vpn').change(function(event) { toggleVpnOptions(); return true; });

  $('#id_location').keyup(function(event) {
    fillMapLocation();
    fillName();
    return true;
  });
  $('#id_geo_lat').change(function(event) { autofillMapEnabled = false; return true; });
  $('#id_geo_long').change(function(event) { autofillMapEnabled = false; return true; });
  $('#id_name').change(function(event) { autofillNameEnabled = false; return true; })

  $('#id_root_pass').after(']').after($('<a />').attr('href', '#').text('generate new').click(generateRandomPassword)).after(' [');

  toggleAutoConfiguration();
  toggleVpnOptions();
  toggleImageGeneratorOptions();
  toggleLocation();
  toggleExtAntenna();
  updatePoolsForProject();
  toggleDead();

  if ($('#id_prefix_len').length) {
    $('#id_pool').change(function(event) {
      updatePrefixLengthsForPool();
      return true;
    });

    updatePrefixLengthsForPool();
  }
});
<|endoftext|>


<commit_before>var core = require('../core'),
    spine = require('./SpineRuntime');

/* Esoteric Software SPINE wrapper for pixi.js */

spine.Bone.yDown = true;

/**
 * A class that enables the you to import and run your spine animations in pixi.
 * Spine animation data needs to be loaded using the AssetLoader or SpineLoader before it can be used by this class
 * See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
 *
 * @class
 * @extends Container
 * @namespace PIXI
 * @param spineData {object} The spine data loaded from a spine atlas.
 */
function Spine(spineData)
{
    core.Container.call(this);

    this.spineData = spineData;

    if (!this.spineData)
    {
        throw new Error('Spine data must be preloaded using SpineLoader or AssetLoader: ' + url);
    }

    this.skeleton = new spine.Skeleton(this.spineData);
    this.skeleton.updateWorldTransform();

    this.stateData = new spine.AnimationStateData(this.spineData);
    this.state = new spine.AnimationState(this.stateData);

    this.slotContainers = [];

    for (var i = 0, n = this.skeleton.drawOrder.length; i < n; i++)
    {
        var slot = this.skeleton.drawOrder[i];
        var attachment = slot.attachment;
        var slotContainer = new core.Container();
        this.slotContainers.push(slotContainer);
        this.addChild(slotContainer);

        if (attachment instanceof spine.RegionAttachment)
        {
            var spriteName = attachment.rendererObject.name;
            var sprite = this.createSprite(slot, attachment);
            slot.currentSprite = sprite;
            slot.currentSpriteName = spriteName;
            slotContainer.addChild(sprite);
        }
        else if (attachment instanceof spine.MeshAttachment)
        {
            var mesh = this.createMesh(slot, attachment);
            slot.currentMesh = mesh;
            slot.currentMeshName = attachment.name;
            slotContainer.addChild(mesh);
        }
        else
        {
            continue;
        }

    }

    this.autoUpdate = true;
}

Spine.prototype = Object.create(core.Container.prototype);
Spine.prototype.constructor = Spine;
module.exports = Spine;

Object.defineProperties(Spine.prototype, {
    /**
     * If this flag is set to true, the spine animation will be autoupdated every time
     * the object id drawn. The down side of this approach is that the delta time is
     * automatically calculated and you could miss out on cool effects like slow motion,
     * pause, skip ahead and the sorts. Most of these effects can be achieved even with
     * autoupdate enabled but are harder to achieve.
     *
     * @member {boolean}
     * @memberof Spine#
     * @default true
     */
    autoUpdate: {
        get: function ()
        {
            return (this.updateTransform === Spine.prototype.autoUpdateTransform);
        },

        set: function (value)
        {
            this.updateTransform = value ? Spine.prototype.autoUpdateTransform : core.Container.prototype.updateTransform;
        }
    }
});

/**
 * Update the spine skeleton and its animations by delta time (dt)
 *
 * @param dt {number} Delta time. Time by which the animation should be updated
 */
Spine.prototype.update = function (dt)
{
    this.state.update(dt);
    this.state.apply(this.skeleton);
    this.skeleton.updateWorldTransform();

    var drawOrder = this.skeleton.drawOrder;
    for (var i = 0, n = drawOrder.length; i < n; i++)
    {
        var slot = drawOrder[i];
        var attachment = slot.attachment;
        var slotContainer = this.slotContainers[i];

        if (!attachment)
        {
            slotContainer.visible = false;
            continue;
        }

        var type = attachment.type;
        if (type === spine.AttachmentType.region)
        {
            if (attachment.rendererObject)
            {
                if (!slot.currentSpriteName || slot.currentSpriteName !== attachment.rendererObject.name)
                {
                    var spriteName = attachment.rendererObject.name;
                    if (slot.currentSprite !== undefined)
                    {
                        slot.currentSprite.visible = false;
                    }
                    slot.sprites = slot.sprites || {};
                    if (slot.sprites[spriteName] !== undefined)
                    {
                        slot.sprites[spriteName].visible = true;
                    }
                    else
                    {
                        var sprite = this.createSprite(slot, attachment);
                        slotContainer.addChild(sprite);
                    }
                    slot.currentSprite = slot.sprites[spriteName];
                    slot.currentSpriteName = spriteName;
                }
            }

            var bone = slot.bone;

            slotContainer.position.x = bone.worldX + attachment.x * bone.m00 + attachment.y * bone.m01;
            slotContainer.position.y = bone.worldY + attachment.x * bone.m10 + attachment.y * bone.m11;
            slotContainer.scale.x = bone.worldScaleX;
            slotContainer.scale.y = bone.worldScaleY;

            slotContainer.rotation = -(slot.bone.worldRotation * spine.degRad);

            slot.currentSprite.tint = core.utils.rgb2hex([slot.r,slot.g,slot.b]);
        }
        else if (type === spine.AttachmentType.skinnedmesh)
        {
            if (!slot.currentMeshName || slot.currentMeshName !== attachment.name)
            {
                var meshName = attachment.name;
                if (slot.currentMesh !== undefined)
                {
                    slot.currentMesh.visible = false;
                }

                slot.meshes = slot.meshes || {};

                if (slot.meshes[meshName] !== undefined)
                {
                    slot.meshes[meshName].visible = true;
                }
                else
                {
                    var mesh = this.createMesh(slot, attachment);
                    slotContainer.addChild(mesh);
                }

                slot.currentMesh = slot.meshes[meshName];
                slot.currentMeshName = meshName;
            }

            attachment.computeWorldVertices(slot.bone.skeleton.x, slot.bone.skeleton.y, slot, slot.currentMesh.vertices);

        }
        else
        {
            slotContainer.visible = false;
            continue;
        }
        slotContainer.visible = true;

        slotContainer.alpha = slot.a;
    }
};

/**
 * When autoupdate is set to yes this function is used as pixi's updateTransform function
 *
 * @private
 */
Spine.prototype.autoUpdateTransform = function ()
{
    this.lastTime = this.lastTime || Date.now();
    var timeDelta = (Date.now() - this.lastTime) * 0.001;
    this.lastTime = Date.now();

    this.update(timeDelta);

    core.Container.prototype.updateTransform.call(this);
};

/**
 * Create a new sprite to be used with spine.RegionAttachment
 *
 * @param slot {spine.Slot} The slot to which the attachment is parented
 * @param attachment {spine.RegionAttachment} The attachment that the sprite will represent
 * @private
 */
Spine.prototype.createSprite = function (slot, attachment)
{
    var descriptor = attachment.rendererObject;
    var baseTexture = descriptor.page.rendererObject;
    var spriteRect = new core.math.Rectangle(descriptor.x,
                                        descriptor.y,
                                        descriptor.rotate ? descriptor.height : descriptor.width,
                                        descriptor.rotate ? descriptor.width : descriptor.height);
    var spriteTexture = new core.Texture(baseTexture, spriteRect);
    var sprite = new core.Sprite(spriteTexture);

    var baseRotation = descriptor.rotate ? Math.PI * 0.5 : 0.0;
    sprite.scale.set(descriptor.width / descriptor.originalWidth, descriptor.height / descriptor.originalHeight);
    sprite.rotation = baseRotation - (attachment.rotation * spine.degRad);
    sprite.anchor.x = sprite.anchor.y = 0.5;

    slot.sprites = slot.sprites || {};
    slot.sprites[descriptor.name] = sprite;
    return sprite;
};

/**
 *
 * @param slot {spine.Slot} The slot to which the attachment is parented
 * @param attachment {spine.RegionAttachment} The attachment that the sprite will represent
 * @private
 */
Spine.prototype.createMesh = function (slot, attachment)
{
    var descriptor = attachment.rendererObject;
    var baseTexture = descriptor.page.rendererObject;
    var texture = new core.Texture(baseTexture);

    var strip = new core.Strip(texture);
    strip.drawMode = core.Strip.DrawModes.TRIANGLES;
    strip.canvasPadding = 1.5;

    strip.vertices = new Float32Array(attachment.uvs.length);
    strip.uvs = attachment.uvs;
    strip.indices = attachment.triangles;

    slot.meshes = slot.meshes || {};
    slot.meshes[attachment.name] = strip;

    return strip;
};
<commit_msg>fix some typos in spine<commit_after>var core = require('../core'),
    spine = require('./SpineRuntime');

/* Esoteric Software SPINE wrapper for pixi.js */

spine.Bone.yDown = true;

/**
 * A class that enables the you to import and run your spine animations in pixi.
 * Spine animation data needs to be loaded using the AssetLoader or SpineLoader before it can be used by this class
 * See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
 *
 * @class
 * @extends Container
 * @namespace PIXI
 * @param spineData {object} The spine data loaded from a spine atlas.
 */
function Spine(spineData)
{
    core.Container.call(this);

    if (!spineData)
    {
        throw new Error('The spineData param is required.');
    }

    this.spineData = spineData;

    this.skeleton = new spine.Skeleton(spineData);
    this.skeleton.updateWorldTransform();

    this.stateData = new spine.AnimationStateData(spineData);
    this.state = new spine.AnimationState(stateData);

    this.slotContainers = [];

    for (var i = 0, n = this.skeleton.drawOrder.length; i < n; i++)
    {
        var slot = this.skeleton.drawOrder[i];
        var attachment = slot.attachment;
        var slotContainer = new core.Container();
        this.slotContainers.push(slotContainer);
        this.addChild(slotContainer);

        if (attachment instanceof spine.RegionAttachment)
        {
            var spriteName = attachment.rendererObject.name;
            var sprite = this.createSprite(slot, attachment);
            slot.currentSprite = sprite;
            slot.currentSpriteName = spriteName;
            slotContainer.addChild(sprite);
        }
        else if (attachment instanceof spine.MeshAttachment)
        {
            var mesh = this.createMesh(slot, attachment);
            slot.currentMesh = mesh;
            slot.currentMeshName = attachment.name;
            slotContainer.addChild(mesh);
        }
        else
        {
            continue;
        }

    }

    this.autoUpdate = true;
}

Spine.prototype = Object.create(core.Container.prototype);
Spine.prototype.constructor = Spine;
module.exports = Spine;

Object.defineProperties(Spine.prototype, {
    /**
     * If this flag is set to true, the spine animation will be autoupdated every time
     * the object id drawn. The down side of this approach is that the delta time is
     * automatically calculated and you could miss out on cool effects like slow motion,
     * pause, skip ahead and the sorts. Most of these effects can be achieved even with
     * autoupdate enabled but are harder to achieve.
     *
     * @member {boolean}
     * @memberof Spine#
     * @default true
     */
    autoUpdate: {
        get: function ()
        {
            return (this.updateTransform === Spine.prototype.autoUpdateTransform);
        },

        set: function (value)
        {
            this.updateTransform = value ? Spine.prototype.autoUpdateTransform : core.Container.prototype.updateTransform;
        }
    }
});

/**
 * Update the spine skeleton and its animations by delta time (dt)
 *
 * @param dt {number} Delta time. Time by which the animation should be updated
 */
Spine.prototype.update = function (dt)
{
    this.state.update(dt);
    this.state.apply(this.skeleton);
    this.skeleton.updateWorldTransform();

    var drawOrder = this.skeleton.drawOrder;
    for (var i = 0, n = drawOrder.length; i < n; i++)
    {
        var slot = drawOrder[i];
        var attachment = slot.attachment;
        var slotContainer = this.slotContainers[i];

        if (!attachment)
        {
            slotContainer.visible = false;
            continue;
        }

        var type = attachment.type;
        if (type === spine.AttachmentType.region)
        {
            if (attachment.rendererObject)
            {
                if (!slot.currentSpriteName || slot.currentSpriteName !== attachment.rendererObject.name)
                {
                    var spriteName = attachment.rendererObject.name;
                    if (slot.currentSprite !== undefined)
                    {
                        slot.currentSprite.visible = false;
                    }
                    slot.sprites = slot.sprites || {};
                    if (slot.sprites[spriteName] !== undefined)
                    {
                        slot.sprites[spriteName].visible = true;
                    }
                    else
                    {
                        var sprite = this.createSprite(slot, attachment);
                        slotContainer.addChild(sprite);
                    }
                    slot.currentSprite = slot.sprites[spriteName];
                    slot.currentSpriteName = spriteName;
                }
            }

            var bone = slot.bone;

            slotContainer.position.x = bone.worldX + attachment.x * bone.m00 + attachment.y * bone.m01;
            slotContainer.position.y = bone.worldY + attachment.x * bone.m10 + attachment.y * bone.m11;
            slotContainer.scale.x = bone.worldScaleX;
            slotContainer.scale.y = bone.worldScaleY;

            slotContainer.rotation = -(slot.bone.worldRotation * spine.degRad);

            slot.currentSprite.tint = core.utils.rgb2hex([slot.r,slot.g,slot.b]);
        }
        else if (type === spine.AttachmentType.skinnedmesh)
        {
            if (!slot.currentMeshName || slot.currentMeshName !== attachment.name)
            {
                var meshName = attachment.name;
                if (slot.currentMesh !== undefined)
                {
                    slot.currentMesh.visible = false;
                }

                slot.meshes = slot.meshes || {};

                if (slot.meshes[meshName] !== undefined)
                {
                    slot.meshes[meshName].visible = true;
                }
                else
                {
                    var mesh = this.createMesh(slot, attachment);
                    slotContainer.addChild(mesh);
                }

                slot.currentMesh = slot.meshes[meshName];
                slot.currentMeshName = meshName;
            }

            attachment.computeWorldVertices(slot.bone.skeleton.x, slot.bone.skeleton.y, slot, slot.currentMesh.vertices);

        }
        else
        {
            slotContainer.visible = false;
            continue;
        }
        slotContainer.visible = true;

        slotContainer.alpha = slot.a;
    }
};

/**
 * When autoupdate is set to yes this function is used as pixi's updateTransform function
 *
 * @private
 */
Spine.prototype.autoUpdateTransform = function ()
{
    this.lastTime = this.lastTime || Date.now();
    var timeDelta = (Date.now() - this.lastTime) * 0.001;
    this.lastTime = Date.now();

    this.update(timeDelta);

    core.Container.prototype.updateTransform.call(this);
};

/**
 * Create a new sprite to be used with spine.RegionAttachment
 *
 * @param slot {spine.Slot} The slot to which the attachment is parented
 * @param attachment {spine.RegionAttachment} The attachment that the sprite will represent
 * @private
 */
Spine.prototype.createSprite = function (slot, attachment)
{
    var descriptor = attachment.rendererObject;
    var baseTexture = descriptor.page.rendererObject;
    var spriteRect = new core.math.Rectangle(descriptor.x,
                                        descriptor.y,
                                        descriptor.rotate ? descriptor.height : descriptor.width,
                                        descriptor.rotate ? descriptor.width : descriptor.height);
    var spriteTexture = new core.Texture(baseTexture, spriteRect);
    var sprite = new core.Sprite(spriteTexture);

    var baseRotation = descriptor.rotate ? Math.PI * 0.5 : 0.0;
    sprite.scale.set(descriptor.width / descriptor.originalWidth, descriptor.height / descriptor.originalHeight);
    sprite.rotation = baseRotation - (attachment.rotation * spine.degRad);
    sprite.anchor.x = sprite.anchor.y = 0.5;

    slot.sprites = slot.sprites || {};
    slot.sprites[descriptor.name] = sprite;
    return sprite;
};

/**
 *
 * @param slot {spine.Slot} The slot to which the attachment is parented
 * @param attachment {spine.RegionAttachment} The attachment that the sprite will represent
 * @private
 */
Spine.prototype.createMesh = function (slot, attachment)
{
    var descriptor = attachment.rendererObject;
    var baseTexture = descriptor.page.rendererObject;
    var texture = new core.Texture(baseTexture);

    var strip = new core.Strip(texture);
    strip.drawMode = core.Strip.DrawModes.TRIANGLES;
    strip.canvasPadding = 1.5;

    strip.vertices = new Float32Array(attachment.uvs.length);
    strip.uvs = attachment.uvs;
    strip.indices = attachment.triangles;

    slot.meshes = slot.meshes || {};
    slot.meshes[attachment.name] = strip;

    return strip;
};
<|endoftext|>


<commit_before>/**
 * Created by Wayuki on 02-Apr-17.
 */
import toastr from 'toastr';
import { routerActions } from 'react-router-redux';
import { getInfo } from '../../../youtube';
import app from '../feathers';

import { VIDEO_PAGE_ACTIONS } from './actionTypes';

export const pageEntered = () => ({
  type: VIDEO_PAGE_ACTIONS.PAGE_ENTERED,
});

export const registerVideo = videoId => (
  (dispatch, getState) => {
    getInfo(videoId).then((item) => {
      dispatch({
        type: VIDEO_PAGE_ACTIONS.REGISTER_VIDEO_INFO,
        videoId,
        video: {
          title: item.snippet.title,
          description: item.snippet.description,
          thumbnail: item.snippet.thumbnails.default.url,
        },
      });
    }).catch((err) => {
      toastr.error(err.message);
      dispatch(routerActions.replace('/'));
    });

    const restLink = `${window.location.protocol}//${window.location.hostname}${window.location.port.length > 0 ? `:${window.location.port}` : ''}/video?v=${videoId}`;
    fetch(restLink, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        v: videoId,
        userId: getState().auth.user._id,
      }),
    }).then((response) => {
      if (response.status >= 200 && response.status < 300) {
        return response;
      }
      throw new Error(response.statusText);
    }).then(response => (
      response.json()
    ))
    .then(({ url, favorite }) => {
      dispatch({
        type: VIDEO_PAGE_ACTIONS.REGISTER_VIDEO,
        src: url,
      });
      dispatch({
        type: VIDEO_PAGE_ACTIONS.SET_FAVORITE_STATE,
        favorite,
      });
    })
    .catch((err) => {
      toastr.error(err.message);
      dispatch(routerActions.replace('/'));
    });
  }
);

export const setFavoriteState = favorite => ({
  type: VIDEO_PAGE_ACTIONS.SET_FAVORITE_STATE,
  favorite,
});

export const createFavorite = () => (
  (dispatch, getState) => new Promise((resolve, reject) => {
    const {
      videoPage: {
        videoId,
        video,
      },
      auth: {
        user: {
          _id: userId,
        },
      },
    } = getState();
    app.service('favorites').find({
      query: {
        videoId,
        userId,
      },
    }).then(({ total }) => {
      if (total < 1) {
        if (video.description.length > 100) {
          video.description = video.description.substring(0, 100);
          video.description += '...';
        }
        return app.service('favorites').create({
          videoId,
          userId,
          ...video,
        });
      } else {
        return false;
      }
    }).then((state) => {
      dispatch(setFavoriteState(true));
      if (state) {
        toastr.success('Video has been added to favorite list.');
      }
      resolve();
    }).catch((err) => {
      toastr.error(err.message);
      reject();
    });
  })
);

export const deleteFavorite = () => (
  (dispatch, getState) => new Promise((resolve, reject) => {
    const {
      videoPage: {
        favorite,
        videoId,
      },
      auth: {
        user: {
          _id : userId,
        },
      },
    } = getState();
    app.service('favorites').remove(null, {
      videoId,
      userId,
    }).then(() => {
      dispatch(setFavoriteState(false));
      toastr.success('Video has been removed from favorite list.');
      resolve();
    }).catch((err) => {
      toastr.error(err.message);
      reject(err);
    });
  })
);

export const handleFavoriteButtonClick = () => (
  (dispatch, getState) => {
    const {
      videoPage: {
        favorite,
        videoId,
      },
      auth: {
        user: {
          _id : userId,
        },
      },
    } = getState();
    if (favorite) {
      dispatch(deleteFavorite());
    } else {
      dispatch(createFavorite());
    }
  }
);

export const resetVideoPage = () => ({
  type: VIDEO_PAGE_ACTIONS.RESET_VIDEO_PAGE,
});

export default () => {};
<commit_msg>Thumbnail in favorites prioritize medium to high to default<commit_after>/**
 * Created by Wayuki on 02-Apr-17.
 */
import toastr from 'toastr';
import { routerActions } from 'react-router-redux';
import { getInfo } from '../../../youtube';
import app from '../feathers';

import { VIDEO_PAGE_ACTIONS } from './actionTypes';

export const pageEntered = () => ({
  type: VIDEO_PAGE_ACTIONS.PAGE_ENTERED,
});

export const registerVideo = videoId => (
  (dispatch, getState) => {
    getInfo(videoId).then((item) => {
      dispatch({
        type: VIDEO_PAGE_ACTIONS.REGISTER_VIDEO_INFO,
        videoId,
        video: {
          title: item.snippet.title,
          description: item.snippet.description,
          thumbnail: item.snippet.thumbnails.medium.url || item.snippet.thumbnails.high.url || item.snippet.thumbnails.default.url,
        },
      });
    }).catch((err) => {
      toastr.error(err.message);
      dispatch(routerActions.replace('/'));
    });

    const restLink = `${window.location.protocol}//${window.location.hostname}${window.location.port.length > 0 ? `:${window.location.port}` : ''}/video?v=${videoId}`;
    fetch(restLink, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        v: videoId,
        userId: getState().auth.user._id,
      }),
    }).then((response) => {
      if (response.status >= 200 && response.status < 300) {
        return response;
      }
      throw new Error(response.statusText);
    }).then(response => (
      response.json()
    ))
    .then(({ url, favorite }) => {
      dispatch({
        type: VIDEO_PAGE_ACTIONS.REGISTER_VIDEO,
        src: url,
      });
      dispatch({
        type: VIDEO_PAGE_ACTIONS.SET_FAVORITE_STATE,
        favorite,
      });
    })
    .catch((err) => {
      toastr.error(err.message);
      dispatch(routerActions.replace('/'));
    });
  }
);

export const setFavoriteState = favorite => ({
  type: VIDEO_PAGE_ACTIONS.SET_FAVORITE_STATE,
  favorite,
});

export const createFavorite = () => (
  (dispatch, getState) => new Promise((resolve, reject) => {
    const {
      videoPage: {
        videoId,
        video,
      },
      auth: {
        user: {
          _id: userId,
        },
      },
    } = getState();
    app.service('favorites').find({
      query: {
        videoId,
        userId,
      },
    }).then(({ total }) => {
      if (total < 1) {
        if (video.description.length > 100) {
          video.description = video.description.substring(0, 100);
          video.description += '...';
        }
        return app.service('favorites').create({
          videoId,
          userId,
          ...video,
        });
      } else {
        return false;
      }
    }).then((state) => {
      dispatch(setFavoriteState(true));
      if (state) {
        toastr.success('Video has been added to favorite list.');
      }
      resolve();
    }).catch((err) => {
      toastr.error(err.message);
      reject();
    });
  })
);

export const deleteFavorite = () => (
  (dispatch, getState) => new Promise((resolve, reject) => {
    const {
      videoPage: {
        favorite,
        videoId,
      },
      auth: {
        user: {
          _id : userId,
        },
      },
    } = getState();
    app.service('favorites').remove(null, {
      videoId,
      userId,
    }).then(() => {
      dispatch(setFavoriteState(false));
      toastr.success('Video has been removed from favorite list.');
      resolve();
    }).catch((err) => {
      toastr.error(err.message);
      reject(err);
    });
  })
);

export const handleFavoriteButtonClick = () => (
  (dispatch, getState) => {
    const {
      videoPage: {
        favorite,
        videoId,
      },
      auth: {
        user: {
          _id : userId,
        },
      },
    } = getState();
    if (favorite) {
      dispatch(deleteFavorite());
    } else {
      dispatch(createFavorite());
    }
  }
);

export const resetVideoPage = () => ({
  type: VIDEO_PAGE_ACTIONS.RESET_VIDEO_PAGE,
});

export default () => {};
<|endoftext|>


<commit_before>/** @jsx React.DOM */
'use strict';

var React = require('react'),
    createStoreMixin = require('../mixins/createStoreMixin'),
    RepoStore = require('../stores/RepoStore'),
    UserStore = require('../stores/UserStore'),
    RepoActionCreators = require('../actions/RepoActionCreators'),
    PureRenderMixin = require('react/addons').PureRenderMixin,
    Link = require('react-router/Link'),
    PropTypes = React.PropTypes;

var Repo = React.createClass({
  mixins: [createStoreMixin(RepoStore, UserStore), PureRenderMixin],

  propTypes: {
    fullName: PropTypes.string.isRequired
  },

  getStateFromStores() {
    var repo = RepoStore.get(this.props.fullName);

    return {
      repo: repo,
      owner: repo && UserStore.get(repo.owner)
    };
  },

  componentWillMount() {
    RepoActionCreators.requestRepo(this.props.fullName);
  },

  render() {
    var repo = this.state.repo,
        owner = this.state.owner;

    if (!repo || !owner) {
      return Loading {this.props.fullName}...;
    }

    return (

          <Link to='repo' login={owner.login} name={repo.name}>
            {repo.name}
          </Link>
          {' by '}
          <Link to='user' login={owner.login}>
            {owner.login}
          </Link>

{repo.description}

    );
  }
});

module.exports = Repo;<commit_msg>Minor<commit_after>/** @jsx React.DOM */
'use strict';

var React = require('react'),
    createStoreMixin = require('../mixins/createStoreMixin'),
    RepoStore = require('../stores/RepoStore'),
    UserStore = require('../stores/UserStore'),
    RepoActionCreators = require('../actions/RepoActionCreators'),
    PureRenderMixin = require('react/addons').PureRenderMixin,
    Link = require('react-router/Link'),
    PropTypes = React.PropTypes;

var Repo = React.createClass({
  mixins: [createStoreMixin(RepoStore, UserStore), PureRenderMixin],

  propTypes: {
    fullName: PropTypes.string.isRequired
  },

  getStateFromStores() {
    var repo = RepoStore.get(this.props.fullName);

    return {
      repo: repo,
      owner: repo && UserStore.get(repo.owner)
    };
  },

  componentWillMount() {
    RepoActionCreators.requestRepo(this.props.fullName);
  },

  render() {
    var repo = this.state.repo,
        owner = this.state.owner;

    if (!repo || !owner) {
      return Loading {this.props.fullName}...;
    }

    return (

          <Link to='repo' login={owner.login} name={repo.name}>
            {repo.name}
          </Link>
          {' by '}
          <Link to='user' login={owner.login}>
            {owner.login}
          </Link>

{repo.description}

    );
  }
});

module.exports = Repo;<|endoftext|>