mirror of
https://github.com/HabitRPG/habitica.git
synced 2026-05-05 02:58:43 -05:00
Merge pull request #8256 from a2lin/equipment_search
Adds a free-text filter (search) to the equipment page.
This commit is contained in:
@@ -450,4 +450,84 @@ describe('Inventory Controller', function() {
|
||||
expect(scope.hasAllTimeTravelerItemsOfType('mounts')).to.eql(true);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Gear search filter', function() {
|
||||
var wrap = function(text) {
|
||||
return {'text': function() {return text;}};
|
||||
}
|
||||
|
||||
var toText = function(list) {
|
||||
return _.map(list, function(ele) { return ele.text(); });
|
||||
}
|
||||
|
||||
var gearByClass, gearByType;
|
||||
|
||||
beforeEach(function() {
|
||||
scope.$digest();
|
||||
gearByClass = {'raw': [wrap('kale'), wrap('sashimi')],
|
||||
'cooked': [wrap('chicken'), wrap('potato')]};
|
||||
|
||||
gearByType = {'veg': [wrap('kale'), wrap('potato')],
|
||||
'not': [wrap('chicken'), wrap('sashimi')]};
|
||||
scope.gearByClass = gearByClass;
|
||||
scope.gearByType = gearByType;
|
||||
scope.equipmentQuery.query = 'a';
|
||||
});
|
||||
|
||||
it('filters nothing if equipmentQuery is nothing', function() {
|
||||
scope.equipmentQuery.query = '';
|
||||
scope.$digest();
|
||||
expect(toText(scope.filteredGearByClass['raw'])).to.eql(['kale', 'sashimi']);
|
||||
expect(toText(scope.filteredGearByClass['cooked'])).to.eql(['chicken', 'potato']);
|
||||
expect(toText(scope.filteredGearByType['veg'])).to.eql(['kale', 'potato']);
|
||||
expect(toText(scope.filteredGearByType['not'])).to.eql(['chicken', 'sashimi']);
|
||||
});
|
||||
|
||||
it('filters out gear if class gear changes', function() {
|
||||
scope.$digest();
|
||||
expect(toText(scope.filteredGearByClass['raw'])).to.eql(['kale', 'sashimi']);
|
||||
expect(toText(scope.filteredGearByClass['cooked'])).to.eql(['potato']);
|
||||
|
||||
scope.gearByClass['raw'].push(wrap('zucchini'));
|
||||
scope.gearByClass['cooked'].push(wrap('pizza'));
|
||||
scope.$digest();
|
||||
expect(toText(scope.filteredGearByClass['raw'])).to.eql(['kale', 'sashimi']);
|
||||
expect(toText(scope.filteredGearByClass['cooked'])).to.eql(['potato', 'pizza']);
|
||||
});
|
||||
|
||||
it('filters out gear if typed gear changes', function() {
|
||||
scope.$digest();
|
||||
expect(toText(scope.filteredGearByType['veg'])).to.eql(['kale', 'potato']);
|
||||
expect(toText(scope.filteredGearByType['not'])).to.eql(['sashimi']);
|
||||
|
||||
scope.gearByType['veg'].push(wrap('zucchini'));
|
||||
scope.gearByType['not'].push(wrap('pizza'));
|
||||
|
||||
scope.$digest();
|
||||
expect(toText(scope.filteredGearByType['veg'])).to.eql(['kale', 'potato']);
|
||||
expect(toText(scope.filteredGearByType['not'])).to.eql(['sashimi', 'pizza']);
|
||||
});
|
||||
|
||||
it('filters out gear if filter query changes', function() {
|
||||
scope.equipmentQuery.query = 'c';
|
||||
scope.$digest();
|
||||
|
||||
expect(toText(scope.filteredGearByClass['raw'])).to.eql([]);
|
||||
expect(toText(scope.filteredGearByClass['cooked'])).to.eql(['chicken']);
|
||||
expect(toText(scope.filteredGearByType['veg'])).to.eql([]);
|
||||
expect(toText(scope.filteredGearByType['not'])).to.eql(['chicken']);
|
||||
});
|
||||
|
||||
it('returns the right filtered gear', function() {
|
||||
var equipment = [wrap('spicy tuna'), wrap('dragon'), wrap('rainbow'), wrap('caterpillar')];
|
||||
expect(toText(scope.equipmentSearch(equipment, 'ra'))).to.eql(['dragon', 'rainbow']);
|
||||
});
|
||||
|
||||
it('returns the right filtered gear if the source gear has unicode', function() {
|
||||
// blue hat, red hat, red shield
|
||||
var equipment = [wrap('藍色軟帽'), wrap('紅色軟帽'), wrap('紅色盾牌')];
|
||||
// searching for 'red' gives red hat, red shield
|
||||
expect(toText(scope.equipmentSearch(equipment, '紅色'))).to.eql(['紅色軟帽', '紅色盾牌']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
vertical-align: bottom
|
||||
margin-right: 20px
|
||||
|
||||
.equipment-search
|
||||
max-width: 300px
|
||||
margin-right: 20px
|
||||
|
||||
.well.use-costume-info
|
||||
margin-top: 10px
|
||||
p:first-child
|
||||
|
||||
@@ -8,6 +8,7 @@ habitrpg.controller("InventoryCtrl",
|
||||
|
||||
$scope.selectedEgg = null; // {index: 1, name: "Tiger", value: 5}
|
||||
$scope.selectedPotion = null; // {index: 5, name: "Red", value: 3}
|
||||
$scope.equipmentQuery = {'query': ''};
|
||||
|
||||
_updateDropAnimalCount(user.items);
|
||||
|
||||
@@ -85,6 +86,50 @@ habitrpg.controller("InventoryCtrl",
|
||||
})
|
||||
}, true);
|
||||
|
||||
$scope.equipmentSearch = function(equipment, term) {
|
||||
if (!equipment) return;
|
||||
if (!angular.isString(term) || term.length == 0) {
|
||||
return equipment;
|
||||
}
|
||||
termMatcher = new RegExp(term, 'i');
|
||||
|
||||
var result = [];
|
||||
for (var i = 0; i < equipment.length; i++) {
|
||||
if (termMatcher.test(equipment[i].text())) {
|
||||
result.push(equipment[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
$scope.updateEquipment = function(gearByClass, gearByType, equipmentQuery) {
|
||||
$scope.filteredGearByClass = {};
|
||||
$scope.filteredGearByType = {};
|
||||
_.forEach(gearByClass, function(value, key) {
|
||||
var searchResult = $scope.equipmentSearch(value, equipmentQuery);
|
||||
if (searchResult.length > 0) {
|
||||
$scope.filteredGearByClass[key] = searchResult;
|
||||
}
|
||||
});
|
||||
_.forEach(gearByType, function(value, key) {
|
||||
var searchResult = $scope.equipmentSearch(value, equipmentQuery);
|
||||
if (searchResult.length > 0) {
|
||||
$scope.filteredGearByType[key] = searchResult;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$watch(function(){
|
||||
return ['gearByClass', 'gearByType', 'equipmentQuery'].map(angular.bind($scope, $scope.$eval));
|
||||
}, function(updatedVals) {
|
||||
var gearByClass = updatedVals[0];
|
||||
var gearByType = updatedVals[1];
|
||||
var equipmentQuery = updatedVals[2];
|
||||
$scope.updateEquipment(gearByClass, gearByType, equipmentQuery.query);
|
||||
}, true);
|
||||
|
||||
$scope.updateEquipment($scope.gearByClass, $scope.gearByType, $scope.equipmentQuery.query);
|
||||
|
||||
$scope.chooseEgg = function(egg){
|
||||
if ($scope.selectedEgg && $scope.selectedEgg.key == egg) {
|
||||
return $scope.selectedEgg = null; // clicked same egg, unselect
|
||||
|
||||
@@ -31,16 +31,22 @@ mixin equipmentButton(type)
|
||||
popover-append-to-body='true')
|
||||
|
||||
mixin equipmentList(equipmentType)
|
||||
menu.pets-menu(label='{{::label}}', ng-show='gearByClass[klass]', ng-if='groupingChoice === "klass"',
|
||||
menu.pets-menu(label='{{::label}}', ng-show='filteredGearByClass[klass]', ng-if='groupingChoice === "klass"',
|
||||
ng-repeat='(klass,label) in {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer"), special:env.t("special"), mystery:env.t("mystery"), armoire:env.t("armoireText")}')
|
||||
div(ng-repeat='item in gearByClass[klass] | orderBy: order')
|
||||
div(ng-repeat='item in filteredGearByClass[klass] | orderBy: order')
|
||||
+equipmentButton(equipmentType)
|
||||
menu.pets-menu(label='{{::label}}', ng-show='gearByType[type]', ng-if='groupingChoice === "equipmentType"',
|
||||
menu.pets-menu(label='{{::label}}', ng-show='filteredGearByType[type]', ng-if='groupingChoice === "equipmentType"',
|
||||
ng-repeat='(type,label) in {headAccessory:env.t("headAccessoryCapitalized"), head:env.t("headgearCapitalized"), eyewear:env.t("eyewear"), weapon:env.t("weaponCapitalized"), shield:env.t("offhandCapitalized"), armor:env.t("armorCapitalized"), body:env.t("body"), back:env.t("back")}')
|
||||
div(ng-repeat='item in gearByType[type] | orderBy: order', ng-show='item.klass !== "base"')
|
||||
div(ng-repeat='item in filteredGearByType[type] | orderBy: order', ng-show='item.klass !== "base"')
|
||||
+equipmentButton(equipmentType)
|
||||
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-6
|
||||
.input-group.equipment-search
|
||||
.input-group-addon
|
||||
.glyphicon.glyphicon-search
|
||||
input.form-control(type='text', placeholder=env.t('search'), ng-model='equipmentQuery.query', ng-model-options='{ debounce: 250 }')
|
||||
.row
|
||||
.col-md-6.border-right(ng-controller="SortableInventoryController")
|
||||
h3.equipment-title.hint(popover-trigger='mouseenter',
|
||||
|
||||
Reference in New Issue
Block a user