From 47b68c777d974a47b13b15d511e61e3195b531be Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 4 May 2017 14:19:47 +0200 Subject: [PATCH] Improved item library dialog UI --- rpg-docs/.meteor/packages | 1 + .../itemLibraryDialog/itemLibraryDialog.css | 20 ++++- .../itemLibraryDialog/itemLibraryDialog.html | 82 ++++++++++++------- .../itemLibraryDialog/itemLibraryDialog.js | 64 ++++++++++++--- rpg-docs/config.vulcanize | 1 + rpg-docs/server/publications/library.js | 21 +++-- 6 files changed, 140 insertions(+), 49 deletions(-) diff --git a/rpg-docs/.meteor/packages b/rpg-docs/.meteor/packages index c1e8a81c..3f142441 100644 --- a/rpg-docs/.meteor/packages +++ b/rpg-docs/.meteor/packages @@ -46,3 +46,4 @@ templates:array ecmascript@0.6.1 es5-shim@4.6.15 differential:vulcanize +reactive-dict diff --git a/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.css b/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.css index d96d66b9..5c8d14a9 100644 --- a/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.css +++ b/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.css @@ -2,6 +2,22 @@ background-color: #e4e4e4; } -.item-library-dialog .paper-font-subhead { - color: rgba(0,0,0,0.54); +.item-library-dialog .category-header { + font-size: 16px; +} + +.item-library-dialog .category-header iron-icon { + transition: transform 0.3s ease; +} + +.item-library-dialog .category-header iron-icon.open { + transform: rotate(90deg); +} + +.item-library-dialog table { + border-collapse: collapse; +} + +.item-library-dialog .library-item td { + position: relative; } diff --git a/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html b/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html index 3681e88b..3a8110c9 100644 --- a/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html +++ b/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html @@ -10,32 +10,46 @@
- {{#if ready}} -
- {{#if searchTerm}} - {{#if searchItems.count}} - {{#each item in searchItems}} - {{>libraryItem item=item selected=(isSelected item)}} - {{/each}} - {{else}} +
+ {{#if searchTerm}} + {{#if searchItems.count}} + + + {{#each item in searchItems}} + {{>libraryItem item=item selected=(isSelected item)}} + {{/each}} + +
+ {{else}}{{#if searchReady}} No items match "{{searchTerm}}" - {{/if}} - {{else}} - {{#each category in categories}} -
- {{category.name}} -
- {{#each item in (itemsInCategory category.key)}} - {{>libraryItem item=item selected=(isSelected item)}} - {{/each}} - {{/each}} - {{/if}} -
- {{else}} -
- -
- {{/if}} + {{/if}}{{/if}} + {{#unless searchReady}} +
+ +
+ {{/unless}} + {{else}} + {{#each categories}} +
+ + + {{name}} +
+ + + + {{#each item in (itemsInCategory key)}} + {{>libraryItem item=item selected=(isSelected item)}} + {{/each}} + +
+ {{#unless ready key}} + + {{/unless}} +
+ {{/each}} + {{/if}} +
Cancel @@ -45,10 +59,18 @@ diff --git a/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js b/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js index c68e8b08..c3fecdd6 100644 --- a/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js +++ b/rpg-docs/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js @@ -1,41 +1,74 @@ const librarySubs = new SubsManager(); +const categories = [ + {name: "Weapons", key: "weapons"}, + {name: "Armor", key: "armor"}, + {name: "Adventuring Gear", key: "adventuringGear"}, + {name: "Tools", key: "tools"}, +]; + Template.itemLibraryDialog.onCreated(function(){ this.selectedItem = new ReactiveVar(); this.searchTerm = new ReactiveVar(); - this.ready = new ReactiveVar(); + this.categoriesOpen = new ReactiveVar([]); + this.readyDict = new ReactiveDict(); + this.searchReady = new ReactiveVar(); + librarySubs.subscribe("standardLibraries"); this.autorun(() => { - var handle = librarySubs.subscribe("standardLibraries"); - this.ready.set(handle.ready()); + // Subscribe to all open categories + _.each(this.categoriesOpen.get(), (key) => { + var handle = librarySubs.subscribe("standardLibraryItems", key); + this.autorun(() => { + this.readyDict.set(key, handle.ready()); + }); + }); + }); + this.autorun(() => { + // If we are searching, subscibe to all categories + if (this.searchTerm.get()){ + let handles = _.map(categories, category => + librarySubs.subscribe("standardLibraryItems", category.key) + ); + // Ready when all handles are ready + this.autorun(() => { + this.searchReady.set(_.every(handles, h => h.ready())); + }); + } }); }); Template.itemLibraryDialog.helpers({ - ready(){ - return Template.instance().ready.get(); + ready(key){ + return Template.instance().readyDict.get(key); }, categories(){ - return [ - {name: "Weapons", key: "weapons"}, - {name: "Armor", key: "armor"}, - {name: "Adventuring Gear", key: "adventuringGear"}, - ]; + return categories; }, itemsInCategory(categoryKey){ return LibraryItems.find({ library: "SRDLibraryGA3XWsd", "settings.category": categoryKey, + }, { + sort: {name: 1}, }); }, isSelected(item){ const selected = Template.instance().selectedItem.get(); return selected && selected._id === item._id; }, + isOpen(key){ + const cats = Template.instance().categoriesOpen.get(); + return _.contains(cats, key); + }, searchTerm(){ return Template.instance().searchTerm.get(); }, + searchReady(){ + return Template.instance().searchReady.get(); + }, searchItems(){ const searchTerm = Template.instance().searchTerm.get(); + if (!searchTerm) return; return LibraryItems.find({ library: "SRDLibraryGA3XWsd", name: { @@ -58,6 +91,17 @@ Template.itemLibraryDialog.events({ "click #backButton": function(event, template){ popDialogStack(); }, + "click .category-header": function(event, template){ + let cats = template.categoriesOpen.get(); + const key = this.key; + // Toggle whether this key is in the array or not + if (_.contains(cats, key)){ + cats = _.without(cats, key); + } else { + cats.push(key); + } + template.categoriesOpen.set(cats); + }, "input .search-input, change .search-input": function(event, template){ const value = event.currentTarget.value; template.searchTerm.set(value); diff --git a/rpg-docs/config.vulcanize b/rpg-docs/config.vulcanize index 88a89f37..0e27de89 100644 --- a/rpg-docs/config.vulcanize +++ b/rpg-docs/config.vulcanize @@ -8,6 +8,7 @@ "/components/app-layout/app-scroll-effects/effects/parallax-background.html", "/components/app-layout/app-scroll-effects/effects/resize-title.html", + "/components/iron-collapse/iron-collapse.html", "/components/iron-icon/iron-icon.html", "/components/iron-icons/av-icons.html", "/components/iron-icons/editor-icons.html", diff --git a/rpg-docs/server/publications/library.js b/rpg-docs/server/publications/library.js index b82fcfed..e113a531 100644 --- a/rpg-docs/server/publications/library.js +++ b/rpg-docs/server/publications/library.js @@ -1,9 +1,16 @@ +const standardLibraryIds = [ + "SRDLibraryGA3XWsd", +]; + Meteor.publish("standardLibraries", function(){ - const standardLibraryIds = [ - "SRDLibraryGA3XWsd", - ]; - return [ - LibraryItems.find({library: {$in: standardLibraryIds}}), - Libraries.find({_id: {$in: standardLibraryIds}}), - ]; + return Libraries.find({_id: {$in: standardLibraryIds}}); +}); + +Meteor.publish("standardLibraryItems", function(categoryKey){ + return LibraryItems.find({ + library: {$in: standardLibraryIds}, + "settings.category": categoryKey, + }, { + sort: {name: 1}, + }); });