From d4864dda5fa9e45c67811d378524acb5711c6034 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Fri, 3 May 2019 13:41:49 +0200 Subject: [PATCH 1/4] Fixed error on no meteor.settings file, updated meteor --- app/.meteor/packages | 8 ++++---- app/.meteor/release | 2 +- app/.meteor/versions | 16 ++++++++-------- app/client/views/user/profile/profile.js | 5 ++++- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app/.meteor/packages b/app/.meteor/packages index 815922ae..6244d270 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -25,13 +25,13 @@ chuangbo:marked reywood:iron-router-ga meteor-base@1.4.0 mobile-experience@1.0.5 -mongo@1.6.0 +mongo@1.6.2 blaze-html-templates session@1.2.0 jquery@1.11.10 tracker@1.2.0 logging@1.1.20 -reload@1.2.0 +reload@1.3.0 ejson@1.1.0 spacebars check@1.3.1 @@ -43,11 +43,11 @@ templates:array ecmascript@0.12.4 es5-shim@4.8.0 differential:vulcanize -reactive-dict@1.2.1 +reactive-dict@1.3.0 ongoworks:speakingurl service-configuration@1.0.11 google-config-ui@1.0.1 -dynamic-import@0.5.0 +dynamic-import@0.5.1 ddp-rate-limiter@1.0.7 rate-limit@1.0.9 iron:router diff --git a/app/.meteor/release b/app/.meteor/release index 91e05fc1..97064e19 100644 --- a/app/.meteor/release +++ b/app/.meteor/release @@ -1 +1 @@ -METEOR@1.8.0.2 +METEOR@1.8.1 diff --git a/app/.meteor/versions b/app/.meteor/versions index 73460e95..eecfcb54 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -1,4 +1,4 @@ -accounts-base@1.4.3 +accounts-base@1.4.4 accounts-google@1.3.2 accounts-oauth@1.1.16 accounts-password@1.5.1 @@ -10,8 +10,8 @@ aldeed:schema-deny@1.1.0 aldeed:schema-index@1.1.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 -autoupdate@1.5.1 -babel-compiler@7.2.4 +autoupdate@1.6.0 +babel-compiler@7.3.4 babel-runtime@1.3.0 base64@1.0.11 binary-heap@1.0.11 @@ -31,12 +31,12 @@ ddp@1.4.0 ddp-client@2.3.3 ddp-common@1.4.0 ddp-rate-limiter@1.0.7 -ddp-server@2.2.0 +ddp-server@2.3.0 deps@1.0.12 diff-sequence@1.1.1 differential:vulcanize@3.0.0 dynamic-import@0.5.1 -ecmascript@0.12.6 +ecmascript@0.12.7 ecmascript-runtime@0.7.0 ecmascript-runtime-client@0.8.0 ecmascript-runtime-server@0.7.1 @@ -103,9 +103,9 @@ promise@0.11.2 raix:eventemitter@0.1.3 random@1.1.0 rate-limit@1.0.9 -reactive-dict@1.2.1 +reactive-dict@1.3.0 reactive-var@1.0.11 -reload@1.2.0 +reload@1.3.0 retry@1.1.0 reywood:iron-router-ga@0.7.1 routepolicy@1.1.0 @@ -133,7 +133,7 @@ url@1.2.0 useraccounts:core@1.14.2 useraccounts:iron-routing@1.14.2 useraccounts:polymer@1.14.2 -webapp@1.7.3 +webapp@1.7.4 webapp-hashing@1.0.9 zimme:collection-behaviours@1.1.3 zimme:collection-softremovable@1.0.5 diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index 90234d86..e0dcde84 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -1,6 +1,8 @@ import { format as formatUrl } from 'url'; -const CLIENT_ID = Meteor.settings.public.patreon.clientId; +const CLIENT_ID = Meteor.settings && + Meteor.settings.public.patreon && + Meteor.settings.public.patreon.clientId; Template.profile.onCreated(function(){ this.showApiKey = new ReactiveVar(false); @@ -18,6 +20,7 @@ Template.profile.helpers({ return Template.instance().showApiKey.get(); }, patreonLoginUrl: function(){ + if (!CLIENT_ID) return; return formatUrl({ protocol: 'https', host: 'patreon.com', From 81a3ede86e9d2e86505c72ab971fb1741414d54e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 14:51:48 +0200 Subject: [PATCH 2/4] Substantially improved item libraries UI, locked behind Patreon tier 5 --- app/Model/Library/Library.js | 16 +-- app/Routes/Routes.js | 21 +++- app/client/globalHelpers/isTier5.js | 7 ++ app/client/globalHelpers/patreonLoginUrl.js | 19 +++ app/client/views/layout/layout.html | 14 +-- app/client/views/layout/layout.js | 7 -- .../library/itemLibrary/itemLibrary.html | 29 ----- .../views/library/itemLibrary/itemLibrary.js | 94 -------------- app/client/views/library/libraries.css | 1 + app/client/views/library/libraries.html | 35 ++++++ app/client/views/library/libraries.js | 38 ++++++ app/client/views/library/library.css | 19 --- app/client/views/library/library.html | 64 +++++++--- app/client/views/library/library.js | 117 ++++++++++++++++-- .../library/libraryDeleteConfirmation.html | 18 +++ .../library/libraryDeleteConfirmation.js | 8 ++ .../library/libraryDialog/libraryDialog.html | 34 ++++- .../library/libraryDialog/libraryDialog.js | 34 ++++- .../libraryItemDialog/libraryItemDialog.html | 47 +++---- .../libraryItemDialog/libraryItemDialog.js | 20 +++ app/client/views/patreon/patronsOnly.html | 27 ++++ app/client/views/user/profile/profile.js | 19 --- app/public/custom_components/app-theme.html | 4 + app/server/publications/library.js | 49 +++++++- 24 files changed, 493 insertions(+), 248 deletions(-) create mode 100644 app/client/globalHelpers/isTier5.js create mode 100644 app/client/globalHelpers/patreonLoginUrl.js delete mode 100644 app/client/views/library/itemLibrary/itemLibrary.html delete mode 100644 app/client/views/library/itemLibrary/itemLibrary.js create mode 100644 app/client/views/library/libraries.css create mode 100644 app/client/views/library/libraries.html create mode 100644 app/client/views/library/libraries.js delete mode 100644 app/client/views/library/library.css create mode 100644 app/client/views/library/libraryDeleteConfirmation.html create mode 100644 app/client/views/library/libraryDeleteConfirmation.js rename app/client/views/library/{itemLibrary => }/libraryItemDialog/libraryItemDialog.html (74%) rename app/client/views/library/{itemLibrary => }/libraryItemDialog/libraryItemDialog.js (91%) create mode 100644 app/client/views/patreon/patronsOnly.html diff --git a/app/Model/Library/Library.js b/app/Model/Library/Library.js index edcb8cc1..c8f15706 100644 --- a/app/Model/Library/Library.js +++ b/app/Model/Library/Library.js @@ -10,19 +10,21 @@ Schemas.Library = new SimpleSchema({ Libraries.attachSchema(Schemas.Library); -Libraries.after.remove(function(userId, library) { - LibraryItems.remove({library: library._id}); - LibrarySpells.remove({library: library._id}); -}); +if (Meteor.isServer){ + Libraries.after.remove(function(userId, library) { + LibraryItems.remove({library: library._id}); + LibrarySpells.remove({library: library._id}); + }); +} Meteor.methods({ - removeLibrary: function(libraryId) { + unshareLibraryWithMe: function(libraryId) { let library = Libraries.findOne(libraryId); - let userId = Meteor.userId(); + let userId = Meteor.userId(); if (!library) return; if (library.owner === userId){ - Libraries.remove(libraryId); + throw new Meteor.error("Can't unshare, you own this") } else { if (_.contains(library.readers, userId)){ Libraries.update(libraryId, {$pull: {"readers": userId}}); diff --git a/app/Routes/Routes.js b/app/Routes/Routes.js index 49accc2a..b6803480 100644 --- a/app/Routes/Routes.js +++ b/app/Routes/Routes.js @@ -8,6 +8,8 @@ Router.plugin("ensureSignedIn", { only: [ "profile", "characterList", + "library", + "libraries", ] }); @@ -118,11 +120,28 @@ Router.map(function() { }, }); - this.route("library", { + this.route("libraries", { path: "/library", waitOn: function(){ return subsManager.subscribe("customLibraries"); }, + onAfterAction: function() { + document.title = appName + " - Libraries"; + }, + fastRender: true, + }); + + this.route("library", { + path: "/library/:_id", + waitOn: function(){ + return [ + subsManager.subscribe("libraryItems", this.params._id), + subsManager.subscribe("singleLibrary", this.params._id), + ]; + }, + data: function() { + return Libraries.findOne(this.params._id); + }, onAfterAction: function() { document.title = appName + " - Library"; }, diff --git a/app/client/globalHelpers/isTier5.js b/app/client/globalHelpers/isTier5.js new file mode 100644 index 00000000..1802364f --- /dev/null +++ b/app/client/globalHelpers/isTier5.js @@ -0,0 +1,7 @@ +Template.registerHelper("isTier5", function(){ + let user = Meteor.user(); + if (!user) return false; + patreon = user.patreon; + if (!patreon) return false; + return patreon.entitledCents >= 500 || patreon.entitledCentsOverride >= 500; +}); diff --git a/app/client/globalHelpers/patreonLoginUrl.js b/app/client/globalHelpers/patreonLoginUrl.js new file mode 100644 index 00000000..dbce866d --- /dev/null +++ b/app/client/globalHelpers/patreonLoginUrl.js @@ -0,0 +1,19 @@ +const CLIENT_ID = Meteor.settings && + Meteor.settings.public.patreon && + Meteor.settings.public.patreon.clientId; + +Template.registerHelper("patreonLoginUrl", function() { + if (!CLIENT_ID) return; + return formatUrl({ + protocol: 'https', + host: 'patreon.com', + pathname: '/oauth2/authorize', + query: { + response_type: 'code', + client_id: CLIENT_ID, + redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', + state: Meteor.userId(), + scope: 'identity', + }, + }); +}); diff --git a/app/client/views/layout/layout.html b/app/client/views/layout/layout.html index 14f287e8..1a84ff81 100644 --- a/app/client/views/layout/layout.html +++ b/app/client/views/layout/layout.html @@ -44,14 +44,12 @@ Characters - {{#if isTier5}} - - - - Library (beta) - - - {{/if}} + + + + Libraries (beta) + + diff --git a/app/client/views/layout/layout.js b/app/client/views/layout/layout.js index a1d0945d..c1480d44 100644 --- a/app/client/views/layout/layout.js +++ b/app/client/views/layout/layout.js @@ -17,13 +17,6 @@ Template.appDrawer.helpers({ let post = PatreonPosts.findOne({}, {sort: {date: -1}}); return (post && post.link) || 'https://www.patreon.com/dicecloud'; }, - isTier5: function(){ - let user = Meteor.user(); - if (!user) return false; - patreon = user.patreon; - if (!patreon) return false; - return patreon.entitledCents >= 500 || patreon.entitledCentsOverride >= 500; - }, patreonTier: function(){ let user = Meteor.user(); if (!user) return; diff --git a/app/client/views/library/itemLibrary/itemLibrary.html b/app/client/views/library/itemLibrary/itemLibrary.html deleted file mode 100644 index 87047681..00000000 --- a/app/client/views/library/itemLibrary/itemLibrary.html +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/app/client/views/library/itemLibrary/itemLibrary.js b/app/client/views/library/itemLibrary/itemLibrary.js deleted file mode 100644 index 06c733db..00000000 --- a/app/client/views/library/itemLibrary/itemLibrary.js +++ /dev/null @@ -1,94 +0,0 @@ -const librarySubs = new SubsManager(); - -Template.itemLibrary.onCreated(function(){ - this.selectedTab = new ReactiveVar("0"); - this.librariesOpen = new ReactiveVar([]); - this.readyDict = new ReactiveDict(); - this.autorun(() => { - // Subscribe to all open libraries - _.each(this.librariesOpen.get(), (libraryId) => { - var handle = librarySubs.subscribe("libraryItems", libraryId); - this.autorun(() => { - this.readyDict.set(libraryId, handle.ready()); - }); - }); - }); -}); - -Template.itemLibrary.helpers({ - selectedTab(){ - return Template.instance().selectedTab.get(); - }, - libraries(){ - let userId = Meteor.userId(); - return Libraries.find({ - $or: [ - {readers: userId}, - {writers: userId}, - {owner: userId}, - ], - }); - }, - libraryItems(){ - return LibraryItems.find({ - library: this._id - },{ - sort: {name: 1} - }); - }, - ready(libraryId){ - return Template.instance().readyDict.get(libraryId); - }, - isOpen(libraryId){ - const librariesOpen = Template.instance().librariesOpen.get(); - return _.contains(librariesOpen, libraryId); - }, -}); - -Template.itemLibrary.events({ - "click .library-header": function(event, template){ - let libs = template.librariesOpen.get(); - const libraryId = this._id; - // Toggle whether this key is in the array or not - if (_.contains(libs, libraryId)){ - libs = _.without(libs, libraryId); - } else { - libs.push(libraryId); - } - template.librariesOpen.set(libs); - }, - "click .editLibrary": function(event, instance){ - event.stopPropagation(); - var libraryId = this._id; - pushDialogStack({ - template: "libraryDialog", - data: {libraryId}, - element: event.currentTarget.parentElement.parentElement, - returnElement: () => instance.find(`.library-header[data-id='${libraryId}']`), - }); - }, - "click .addItem": function(event, instance){ - event.stopPropagation(); - var libraryId = this._id; - var itemId = LibraryItems.insert({ - name: "New Library Item", - library: libraryId, - }); - pushDialogStack({ - template: "libraryItemDialog", - data: {itemId}, - element: event.currentTarget, - returnElement: () => instance.find(`.item-name[data-id='${itemId}']`), - }); - }, - "click .item-name": function(event, instance){ - event.stopPropagation(); - var itemId = this._id; - pushDialogStack({ - template: "libraryItemDialog", - data: {itemId}, - element: event.currentTarget, - returnElement: () => instance.find(`.item-name[data-id='${itemId}']`), - }); - }, -}) diff --git a/app/client/views/library/libraries.css b/app/client/views/library/libraries.css new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/app/client/views/library/libraries.css @@ -0,0 +1 @@ + diff --git a/app/client/views/library/libraries.html b/app/client/views/library/libraries.html new file mode 100644 index 00000000..62f3c1a4 --- /dev/null +++ b/app/client/views/library/libraries.html @@ -0,0 +1,35 @@ + diff --git a/app/client/views/library/libraries.js b/app/client/views/library/libraries.js new file mode 100644 index 00000000..28756241 --- /dev/null +++ b/app/client/views/library/libraries.js @@ -0,0 +1,38 @@ +const librarySubs = new SubsManager(); + +Template.libraries.helpers({ + libraries(){ + let userId = Meteor.userId(); + let subs = Meteor.user() && Meteor.user().profile.librarySubscriptions; + return Libraries.find({ + $or: [ + {readers: userId}, + {writers: userId}, + {owner: userId}, + {_id: {$in: subs}} + ], + }, { + sort: {name: 1}, + }); + }, +}); + +Template.libraries.events({ + "click #addLibrary": function(event, instance){ + var libraryId = Libraries.insert({ + name: "New Library", + owner: Meteor.userId(), + }); + pushDialogStack({ + template: "libraryDialog", + data: {libraryId}, + element: event.currentTarget, + returnElement: () => instance.find(`.library[data-id='${libraryId}']`), + callback(data){ + if (data && data.delete){ + Libraries.remove(libraryId); + } + } + }); + }, +}) diff --git a/app/client/views/library/library.css b/app/client/views/library/library.css deleted file mode 100644 index 731d8036..00000000 --- a/app/client/views/library/library.css +++ /dev/null @@ -1,19 +0,0 @@ -.library .item-name { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - cursor: pointer; -} - -.library .library-header { - font-weight: 500; - cursor: pointer; -} - -.library .library-header iron-icon { - transition: transform 0.3s ease; -} - -.library .library-header iron-icon.open { - transform: rotate(90deg); -} diff --git a/app/client/views/library/library.html b/app/client/views/library/library.html index b01f46ff..d5c52035 100644 --- a/app/client/views/library/library.html +++ b/app/client/views/library/library.html @@ -2,31 +2,55 @@
-
+
+
- Item Library + {{name}}
+ {{#if isTier5}}{{#if canUserEdit}} + + {{/if}}{{/if}}
- + {{#if isTier5}} +
+ + + +
+ {{#if canUserSubscribe}} + + + Subscribe + + {{else if canUserUnsubscribe}} + + + Unsubscribe + + {{/if}} +
+ {{/if}} -
- -
{{> itemLibrary}}
- -
-
- - {{#simpleTooltip}}Add Library{{/simpleTooltip}} -
+ {{#if isTier5}} +
+ + {{#each items}} + + +
{{displayName}}
+
+
+ {{/each}} +
+
+
+ + {{#simpleTooltip}}Add Library Item{{/simpleTooltip}} +
+ {{else}} + {{> patronsOnly }} + {{/if}}
diff --git a/app/client/views/library/library.js b/app/client/views/library/library.js index 70d0e89d..5f1e889e 100644 --- a/app/client/views/library/library.js +++ b/app/client/views/library/library.js @@ -1,29 +1,120 @@ const librarySubs = new SubsManager(); Template.library.onCreated(function(){ - this.selectedTab = new ReactiveVar("0"); + this.searchTerm = new ReactiveVar(""); }); Template.library.helpers({ - selectedTab(){ - return Template.instance().selectedTab.get(); + items(){ + let search = Template.instance().searchTerm.get(); + if (search){ + return LibraryItems.find( + { + library: this._id, + $or: [ + { + name: {$regex: new RegExp(".*" + search + ".*", "gi")} + }, + { + libraryname: {$regex: new RegExp(".*" + search + ".*", "gi")} + }, + ], + }, + {sort: {name: 1}}, + ); + } else { + return LibraryItems.find( + {library: this._id}, + {sort: {name: 1}}, + ); + } + }, + displayName(){ + return this.libraryName || this.name; + }, + canUserSubscribe(){ + let user = Meteor.user(); + let userId = user._id; + return !( + _.contains(this.readers, userId) || + _.contains(this.writers, userId) || + this.owner === userId || + _.contains(user.profile.librarySubscriptions, this._id) + ); + }, + canUserUnsubscribe(){ + let user = Meteor.user(); + let userId = user._id; + return ( + _.contains(user.profile.librarySubscriptions, this._id) || + _.contains(this.readers, userId) + ); + }, + canUserEdit(){ + let userId = Meteor.userId(); + return ( + _.contains(this.writers, userId) || + this.owner === userId + ); }, }); Template.library.events({ - "iron-select #libraryTabs": function(event, instance){ - instance.selectedTab.set(event.target.selected); + "input .search-input, change .search-input": function(event, template){ + const value = event.currentTarget.value; + template.searchTerm.set(value); }, - "click #addLibrary": function(event, instance){ - var libraryId = Libraries.insert({ - name: "New Library", - owner: Meteor.userId(), - }); + "click #edit": function(event, instance){ + event.stopPropagation(); + var libraryId = this._id; pushDialogStack({ template: "libraryDialog", data: {libraryId}, - element: event.currentTarget, - returnElement: () => instance.find(`.library-header[data-id='${libraryId}']`), + element: event.currentTarget.parentElement.parentElement, + callback(data){ + if (data && data.delete){ + Router.go('/library'); + Tracker.afterFlush(function(){ + Libraries.remove(libraryId); + }); + } + }, }); }, -}) + "click #addLibraryItem": function(event, instance){ + event.stopPropagation(); + var libraryId = this._id; + var itemId = LibraryItems.insert({ + name: "New Library Item", + library: libraryId, + }); + pushDialogStack({ + template: "libraryItemDialog", + data: {itemId}, + element: event.currentTarget, + returnElement: () => instance.find(`.item[data-id='${itemId}']`), + }); + }, + "click .item": function(event, instance){ + event.stopPropagation(); + var itemId = this._id; + pushDialogStack({ + template: "libraryItemDialog", + data: {itemId}, + element: event.currentTarget, + returnElement: () => instance.find(`.item[data-id='${itemId}']`), + }); + }, + "click #subscribe": function(event, instance){ + Meteor.users.update(Meteor.userId(), { + $addToSet: {"profile.librarySubscriptions": this._id}, + }); + }, + "click #unsubscribe": function(event, instance){ + let userId = Meteor.userId(); + Meteor.users.update(userId, { + $pull: {"profile.librarySubscriptions": this._id}, + }); + Meteor.call("unshareLibraryWithMe", this._id); + }, +}); diff --git a/app/client/views/library/libraryDeleteConfirmation.html b/app/client/views/library/libraryDeleteConfirmation.html new file mode 100644 index 00000000..3068e090 --- /dev/null +++ b/app/client/views/library/libraryDeleteConfirmation.html @@ -0,0 +1,18 @@ + diff --git a/app/client/views/library/libraryDeleteConfirmation.js b/app/client/views/library/libraryDeleteConfirmation.js new file mode 100644 index 00000000..20ef660a --- /dev/null +++ b/app/client/views/library/libraryDeleteConfirmation.js @@ -0,0 +1,8 @@ +Template.libraryDeleteConfirmation.events({ + "click #deleteButton": function(event, instance) { + popDialogStack(true); + }, + "click .cancelButton": function(event, instance){ + popDialogStack(); + }, +}); diff --git a/app/client/views/library/libraryDialog/libraryDialog.html b/app/client/views/library/libraryDialog/libraryDialog.html index 3fc83637..1eff7433 100644 --- a/app/client/views/library/libraryDialog/libraryDialog.html +++ b/app/client/views/library/libraryDialog/libraryDialog.html @@ -1,15 +1,39 @@ diff --git a/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js b/app/client/views/library/libraryItemDialog/libraryItemDialog.js similarity index 91% rename from app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js rename to app/client/views/library/libraryItemDialog/libraryItemDialog.js index c258705d..3f82c681 100644 --- a/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js +++ b/app/client/views/library/libraryItemDialog/libraryItemDialog.js @@ -1,3 +1,9 @@ +Template.libraryItemDialog.onCreated(function(){ + this.autorun(() => { + this.subscribe('libraryItem', Template.currentData().itemId); + }); +}); + Template.libraryItemDialog.helpers({ item(){ return LibraryItems.findOne(this.itemId); @@ -55,6 +61,20 @@ Template.libraryItemDialog.helpers({ thunder: 12, }; return ref[damageType]; + }, + ready(){ + return Template.instance().subscriptionsReady(); + }, + cantEdit(){ + let item = LibraryItems.findOne(this.itemId); + if (!item) return; + let library = Libraries.findOne(item.library); + if (!library) return; + let userId = Meteor.userId(); + return !( + library.owner === userId || + _.contains(library.writers, userId) + ); } }); diff --git a/app/client/views/patreon/patronsOnly.html b/app/client/views/patreon/patronsOnly.html new file mode 100644 index 00000000..27c55c05 --- /dev/null +++ b/app/client/views/patreon/patronsOnly.html @@ -0,0 +1,27 @@ + diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index e0dcde84..f3df5f10 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -1,9 +1,5 @@ import { format as formatUrl } from 'url'; -const CLIENT_ID = Meteor.settings && - Meteor.settings.public.patreon && - Meteor.settings.public.patreon.clientId; - Template.profile.onCreated(function(){ this.showApiKey = new ReactiveVar(false); this.loadingPatreon = new ReactiveVar(false); @@ -19,21 +15,6 @@ Template.profile.helpers({ showApiKey: function(){ return Template.instance().showApiKey.get(); }, - patreonLoginUrl: function(){ - if (!CLIENT_ID) return; - return formatUrl({ - protocol: 'https', - host: 'patreon.com', - pathname: '/oauth2/authorize', - query: { - response_type: 'code', - client_id: CLIENT_ID, - redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', - state: Meteor.userId(), - scope: 'identity', - }, - }); - }, patreon: function(){ let user = Meteor.user(); return user && user.patreon || {}; diff --git a/app/public/custom_components/app-theme.html b/app/public/custom_components/app-theme.html index e84c18cb..aff91794 100644 --- a/app/public/custom_components/app-theme.html +++ b/app/public/custom_components/app-theme.html @@ -70,4 +70,8 @@ --paper-diff-slider-knob-color: #00BCD4; --paper-diff-slider-pin-color: #00BCD4; } + .white-text paper-input { + /* Input foreground color */ + --paper-input-container-input-color: rgba(255,255,255,0.87); + } diff --git a/app/server/publications/library.js b/app/server/publications/library.js index 3ab18ce3..94d9df78 100644 --- a/app/server/publications/library.js +++ b/app/server/publications/library.js @@ -25,16 +25,61 @@ Meteor.publish("standardLibrarySpells", function(level){ }); Meteor.publish("customLibraries", function(){ - userId = this.userId; + const userId = this.userId; + let user = Meteor.user() + let subs = user && user.profile && user.profile.librarySubscriptions; return Libraries.find({ $or: [ {readers: userId}, {writers: userId}, {owner: userId}, + {public: true, _id: {$in: subs || []}}, + ], + }); +}); + +Meteor.publish("singleLibrary", function(id){ + const userId = this.userId; + return Libraries.find({ + _id: id, + $or: [ + {readers: userId}, + {writers: userId}, + {owner: userId}, + {public: true}, ], }); }); Meteor.publish("libraryItems", function(libraryId){ - return LibraryItems.find({library: libraryId}); + return LibraryItems.find({ + library: libraryId + }, { + fields: { + name: 1, + libraryName: 1, + library: 1, + }, + }); +}); + +Meteor.publish("libraryItem", function(itemId){ + let cursor = LibraryItems.find(itemId); + let item = cursor.fetch()[0]; + let userId = Meteor.userId(); + if (!item) return []; + let library = Libraries.findOne(item.library); + if (!library) { + throw new Meteor.Error("Library item " + item._id + " is an orphan"); + } + if ( + library.public || + library.owner === userId || + _.contains(library.readers, userId) || + _.contains(library.writers, userId) + ) { + return cursor; + } else { + return []; + } }); From 85e3b0724a9855d630920056a921b0ad272299b6 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 14:51:58 +0200 Subject: [PATCH 3/4] Added a skip button to the new user experience --- .../character/newUserStepper/newUserStepper.html | 13 ++++++++++++- .../character/newUserStepper/newUserStepper.js | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/client/views/character/newUserStepper/newUserStepper.html b/app/client/views/character/newUserStepper/newUserStepper.html index e4cce0e4..444817e3 100644 --- a/app/client/views/character/newUserStepper/newUserStepper.html +++ b/app/client/views/character/newUserStepper/newUserStepper.html @@ -4,19 +4,30 @@

To get started, add a feature

+
+ Skip +

Add a racial effect to set your speed

+
+ Skip +

View your speed stat

+
+ Skip +
- Done! If you get stuck, be sure to check out the guide, or ask for help using the feedback form +

+ Done! If you get stuck, be sure to check out the guide, or ask for help using the feedback form +

Finish
diff --git a/app/client/views/character/newUserStepper/newUserStepper.js b/app/client/views/character/newUserStepper/newUserStepper.js index c45acd9a..a11becdb 100644 --- a/app/client/views/character/newUserStepper/newUserStepper.js +++ b/app/client/views/character/newUserStepper/newUserStepper.js @@ -46,6 +46,10 @@ Template.newUserStepper.events({ const stepper = instance.find("paper-stepper"); stepper.continue(); }, + "click .skip-button": function(event, instance){ + const stepper = instance.find("paper-stepper"); + stepper.continue(); + }, }); Template.stats.events({ From b3aeaf06eacfbf7800627b870527eaa8b611f0f5 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 14:54:30 +0200 Subject: [PATCH 4/4] Fixed an error when deleting categories from library items without any settings --- app/client/views/character/inventory/inventory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/views/character/inventory/inventory.js b/app/client/views/character/inventory/inventory.js index 4234ecff..de5c62ab 100644 --- a/app/client/views/character/inventory/inventory.js +++ b/app/client/views/character/inventory/inventory.js @@ -157,7 +157,7 @@ Template.inventory.events({ } // Make the library item into a regular item let item = _.omit(result, "libraryName", "library", "attacks", "effects"); - delete item.settings.category; + if (item.settings && item.settings.category) delete item.settings.category; // Update the item to match library item Items.update(itemId, {$set: item}); // Copy over attacks and effects