diff --git a/app/Model/Library/Library.js b/app/Model/Library/Library.js
index 6688d0e5..edcb8cc1 100644
--- a/app/Model/Library/Library.js
+++ b/app/Model/Library/Library.js
@@ -2,14 +2,38 @@ Libraries = new Mongo.Collection("library");
Schemas.Library = new SimpleSchema({
name: {type: String},
- owner: {type: String, regEx: SimpleSchema.RegEx.Id},
- readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
- writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
- public: {type: Boolean, defaultValue: false},
+ owner: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
+ readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1},
+ writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1},
+ public: {type: Boolean, defaultValue: false, index: 1},
});
Libraries.attachSchema(Schemas.Library);
+Libraries.after.remove(function(userId, library) {
+ LibraryItems.remove({library: library._id});
+ LibrarySpells.remove({library: library._id});
+});
+
+Meteor.methods({
+ removeLibrary: function(libraryId) {
+ let library = Libraries.findOne(libraryId);
+ let userId = Meteor.userId();
+
+ if (!library) return;
+ if (library.owner === userId){
+ Libraries.remove(libraryId);
+ } else {
+ if (_.contains(library.readers, userId)){
+ Libraries.update(libraryId, {$pull: {"readers": userId}});
+ }
+ if (_.contains(library.writers, userId)){
+ Libraries.update(libraryId, {$pull: {"writers": userId}});
+ }
+ }
+ },
+});
+
Libraries.allow({
insert(userId, doc) {
return userId && doc.owner === userId;
@@ -18,16 +42,14 @@ Libraries.allow({
return canEdit(userId, doc);
},
remove(userId, doc) {
- return canEdit(userId, doc);
+ return userId && doc.owner === userId;
},
fetch: ["owner", "writers"],
});
Libraries.deny({
- // For now, only admins can manage libraries
insert(userId, doc){
- var user = Meteor.users.findOne(userId);
- return !user || !_.contains(user.roles, "admin");
+ return !Meteor.users.findOne(userId);
},
update(userId, doc, fields, modifier) {
// Can't change owners
diff --git a/app/Model/Library/LibraryAttacks.js b/app/Model/Library/LibraryAttacks.js
index d606acd5..9d111498 100644
--- a/app/Model/Library/LibraryAttacks.js
+++ b/app/Model/Library/LibraryAttacks.js
@@ -1,7 +1,7 @@
Schemas.LibraryAttacks = new SimpleSchema({
name: {
type: String,
- defaultValue: "New Attack",
+ optional: true,
trim: false,
},
details: {
diff --git a/app/Model/Library/LibraryEffects.js b/app/Model/Library/LibraryEffects.js
index 4abcb1ef..38389d53 100644
--- a/app/Model/Library/LibraryEffects.js
+++ b/app/Model/Library/LibraryEffects.js
@@ -9,7 +9,6 @@ Schemas.LibraryEffects = new SimpleSchema({
defaultValue: "add",
allowedValues: [
"base",
- "proficiency",
"add",
"mul",
"min",
diff --git a/app/Model/Library/LibraryItems.js b/app/Model/Library/LibraryItems.js
index 569e1df9..f95cd95e 100644
--- a/app/Model/Library/LibraryItems.js
+++ b/app/Model/Library/LibraryItems.js
@@ -42,3 +42,50 @@ LibraryItems.allow({
},
fetch: ["library"],
});
+
+Meteor.methods({
+ updateLibraryItemEffect: function({itemId, effectIndex, field, value, unsetField}){
+ let libraryId = LibraryItems.findOne(itemId).library;
+ let userId = Meteor.userId();
+ if (!Libraries.canEdit(userId, libraryId)) return;
+ let modifier = {
+ $set: {
+ [`effects.${effectIndex}.${field}`]: value,
+ }
+ };
+ if (unsetField){
+ modifier.$unset = {
+ [`effects.${effectIndex}.${unsetField}`]: 1,
+ }
+ }
+ LibraryItems.update(itemId, modifier);
+ },
+ removeLibraryItemEffect: function({itemId, effectIndex}){
+ let libraryId = LibraryItems.findOne(itemId).library;
+ let userId = Meteor.userId();
+ if (!Libraries.canEdit(userId, libraryId)) return;
+ LibraryItems.update(itemId, {$unset : {
+ [`effects.${effectIndex}`] : 1,
+ }});
+ LibraryItems.update(itemId, {$pull : {"effects" : null}});
+ },
+ updateLibraryItemAttack: function({itemId, attackIndex, field, value}){
+ let libraryId = LibraryItems.findOne(itemId).library;
+ let userId = Meteor.userId();
+ if (!Libraries.canEdit(userId, libraryId)) return;
+ LibraryItems.update(itemId, {
+ $set: {
+ [`attacks.${attackIndex}.${field}`]: value,
+ }
+ });
+ },
+ removeLibraryItemAttack: function({itemId, attackIndex}){
+ let libraryId = LibraryItems.findOne(itemId).library;
+ let userId = Meteor.userId();
+ if (!Libraries.canEdit(userId, libraryId)) return;
+ LibraryItems.update(itemId, {$unset : {
+ [`attacks.${attackIndex}`] : 1,
+ }});
+ LibraryItems.update(itemId, {$pull : {"attacks" : null}});
+ },
+})
diff --git a/app/Model/Users/Users.js b/app/Model/Users/Users.js
index bdbbdda4..5f6b2a7e 100644
--- a/app/Model/Users/Users.js
+++ b/app/Model/Users/Users.js
@@ -3,6 +3,10 @@ Schemas.UserProfile = new SimpleSchema({
type: String,
optional: true,
},
+ librarySubscriptions: {
+ type: [String],
+ defaultValue: [],
+ },
});
Schemas.User = new SimpleSchema({
diff --git a/app/Routes/Routes.js b/app/Routes/Routes.js
index 5d67332a..49accc2a 100644
--- a/app/Routes/Routes.js
+++ b/app/Routes/Routes.js
@@ -121,7 +121,7 @@ Router.map(function() {
this.route("library", {
path: "/library",
waitOn: function(){
- return subsManager.subscribe("standardLibraries");
+ return subsManager.subscribe("customLibraries");
},
onAfterAction: function() {
document.title = appName + " - Library";
diff --git a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html
index 1dcb352e..50d6189f 100644
--- a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html
+++ b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html
@@ -48,6 +48,25 @@
{{/unless}}
{{/each}}
+ {{#each customLibraries}}
+
+
+
+ {{name}}
+
+
+
+
+ {{#each item in (itemsInLibrary _id)}}
+ {{>libraryItem item=item selected=(isSelected item)}}
+ {{/each}}
+
+
+ {{#unless ready _id}}
+
+ {{/unless}}
+
+ {{/each}}
{{/if}}
diff --git a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js
index 7ca93920..c21a9aba 100644
--- a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js
+++ b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js
@@ -7,6 +7,13 @@ const categories = [
{name: "Tools", key: "tools"},
];
+const categoryKeys = [
+ "weapons",
+ "armor",
+ "adventuringGear",
+ "tools",
+];
+
Template.itemLibraryDialog.onCreated(function(){
this.selectedItem = new ReactiveVar();
this.searchTerm = new ReactiveVar();
@@ -14,10 +21,17 @@ Template.itemLibraryDialog.onCreated(function(){
this.readyDict = new ReactiveDict();
this.searchReady = new ReactiveVar();
librarySubs.subscribe("standardLibraries");
+ librarySubs.subscribe("customLibraries");
+
this.autorun(() => {
// Subscribe to all open categories
_.each(this.categoriesOpen.get(), (key) => {
- var handle = librarySubs.subscribe("standardLibraryItems", key);
+ let handle;
+ if (_.contains(categoryKeys, key)){
+ handle = librarySubs.subscribe("standardLibraryItems", key);
+ } else {
+ handle = librarySubs.subscribe("libraryItems", key);
+ }
this.autorun(() => {
this.readyDict.set(key, handle.ready());
});
@@ -70,12 +84,29 @@ Template.itemLibraryDialog.helpers({
const searchTerm = Template.instance().searchTerm.get();
if (!searchTerm) return;
return LibraryItems.find({
- library: "SRDLibraryGA3XWsd",
name: {
$regex: new RegExp(".*" + searchTerm + ".*", "gi")
},
});
},
+ customLibraries(){
+ let userId = Meteor.userId();
+ return Libraries.find({
+ $or: [
+ {readers: userId},
+ {writers: userId},
+ {owner: userId},
+ ],
+ });
+ },
+ itemsInLibrary(libraryId){
+ return LibraryItems.find({
+ library: libraryId,
+ }, {
+ sort: {name: 1},
+ });
+ },
+
});
Template.itemLibraryDialog.events({
@@ -93,7 +124,7 @@ Template.itemLibraryDialog.events({
},
"click .category-header": function(event, template){
let cats = template.categoriesOpen.get();
- const key = this.key;
+ const key = this.key || this._id;
// Toggle whether this key is in the array or not
if (_.contains(cats, key)){
cats = _.without(cats, key);
diff --git a/app/client/views/library/itemLibrary/itemLibrary.html b/app/client/views/library/itemLibrary/itemLibrary.html
index 5fbf353b..87047681 100644
--- a/app/client/views/library/itemLibrary/itemLibrary.html
+++ b/app/client/views/library/itemLibrary/itemLibrary.html
@@ -1,5 +1,29 @@
- {{#each items}}
- {{> libraryItem}}
+ {{#each libraries}}
+
+
+ {{#each libraryItems}}
+
+ {{name}}
+
+ {{/each}}
+ {{#unless ready _id}}
+
+ {{/unless}}
+
{{/each}}
diff --git a/app/client/views/library/itemLibrary/itemLibrary.js b/app/client/views/library/itemLibrary/itemLibrary.js
index 480effcc..06c733db 100644
--- a/app/client/views/library/itemLibrary/itemLibrary.js
+++ b/app/client/views/library/itemLibrary/itemLibrary.js
@@ -1,7 +1,94 @@
+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({
- items(){
- return Items.find({charId: {$in: [
- "SRDLibrary",
- ]}});
+ 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/itemLibrary/libraryItemDialog/libraryItemDialog.html b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.html
new file mode 100644
index 00000000..8fcfce0d
--- /dev/null
+++ b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.html
@@ -0,0 +1,88 @@
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
diff --git a/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js
new file mode 100644
index 00000000..c258705d
--- /dev/null
+++ b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js
@@ -0,0 +1,204 @@
+Template.libraryItemDialog.helpers({
+ item(){
+ return LibraryItems.findOne(this.itemId);
+ },
+ calculationOrValue(){
+ return this.calculation || this.value;
+ },
+ indexedEffects(){
+ let item = LibraryItems.findOne(this.itemId);
+ if (!item) return;
+ return _.map(item.effects, (effect, index) => {
+ if (!effect) return;
+ effect.index = index;
+ return effect;
+ });
+ },
+ indexedAttacks(){
+ let item = LibraryItems.findOne(this.itemId);
+ if (!item) return;
+ return _.map(item.attacks, (attack, index) => {
+ if (!attack) return;
+ attack.index = index;
+ return attack;
+ });
+ },
+ operationIndex(operation){
+ const ref = {
+ base: 0,
+ add: 1,
+ mul: 2,
+ min: 3,
+ max: 4,
+ advantage: 5,
+ disadvantage: 6,
+ passiveAdd: 7,
+ fail: 8,
+ conditional: 9,
+ };
+ return ref[operation];
+ },
+ damageTypeIndex(damageType){
+ const ref = {
+ bludgeoning: 0,
+ piercing: 1,
+ slashing: 2,
+ acid: 3,
+ cold: 4,
+ fire: 5,
+ force: 6,
+ lightning: 7,
+ necrotic: 8,
+ poison: 9,
+ psychic: 10,
+ radiant: 11,
+ thunder: 12,
+ };
+ return ref[damageType];
+ }
+});
+
+const bind = function(field){
+ return _.debounce(function(event){
+ const input = event.currentTarget;
+ var value = input.value;
+ LibraryItems.update(this.itemId, {
+ $set: {[field]: value}
+ }, {
+ removeEmptyStrings: false,
+ trimStrings: false,
+ });
+ }, 300);
+};
+
+Template.libraryItemDialog.events({
+ "click #backButton": function(){
+ popDialogStack();
+ },
+ "click #deleteButton": function(){
+ LibraryItems.remove(this.itemId);
+ popDialogStack();
+ },
+ "input #libraryItemLibraryNameInput": bind("libraryName"),
+ "input #libraryItemNameInput": bind("name"),
+ "input #libraryItemPluralInput": bind("plural"),
+ "input #libraryItemQuantityInput": bind("quantity"),
+ "input #libraryItemValueInput": bind("value"),
+ "input #libraryItemWeightInput": bind("weight"),
+ "change #attunementCheckbox": function(event){
+ LibraryItems.update(this.itemId, {
+ $set: {requiresAttunement: event.currentTarget.checked}
+ });
+ },
+ "change #incrementCheckbox": function(event){
+ LibraryItems.update(this.itemId, {
+ $set: {"settings.showIncrement": event.currentTarget.checked}
+ });
+ },
+ "input #libraryItemDescriptionInput": bind("description"),
+
+ // Effects
+ "click #addEffect": function(event, template){
+ LibraryItems.update(template.data.itemId, {
+ $push: {
+ effects: {operation: "add"}
+ }
+ });
+ },
+ "iron-select .operationMenu": function(event, template){
+ var detail = event.originalEvent.detail;
+ var opName = detail.item.getAttribute("name");
+ if (opName == this.operation) return;
+ Meteor.call("updateLibraryItemEffect", {
+ itemId: template.data.itemId,
+ effectIndex: this.index,
+ field: "operation",
+ value: opName,
+ });
+ },
+ "input .LibraryItemEffectStat": _.debounce(function(event, template){
+ Meteor.call("updateLibraryItemEffect", {
+ itemId: template.data.itemId,
+ effectIndex: this.index,
+ field: "stat",
+ value: event.currentTarget.value,
+ });
+ }, 300),
+ "input .LibraryItemEffectValue": _.debounce(function(event, template){
+ let value = event.currentTarget.value;
+ if (value && _.isFinite(+value)){
+ Meteor.call("updateLibraryItemEffect", {
+ itemId: template.data.itemId,
+ effectIndex: this.index,
+ field: "value",
+ unsetField: "calculation",
+ value,
+ });
+ } else {
+ Meteor.call("updateLibraryItemEffect", {
+ itemId: template.data.itemId,
+ effectIndex: this.index,
+ field: "calculation",
+ unsetField: "value",
+ value,
+ });
+ }
+ }, 300),
+ "click .deleteEffect": function (event, template) {
+ Meteor.call("removeLibraryItemEffect", {
+ itemId: template.data.itemId,
+ effectIndex: this.index,
+ });
+ },
+
+ // Attacks
+ "click #addAttack": function(event, template){
+ LibraryItems.update(template.data.itemId, {
+ $push: {
+ attacks: {damageType: "slashing"}
+ }
+ });
+ },
+ "iron-select .damageTypeMenu": function(event, template){
+ var detail = event.originalEvent.detail;
+ var damageType = detail.item.getAttribute("name");
+ if (damageType == this.damageType) return;
+ Meteor.call("updateLibraryItemAttack", {
+ itemId: template.data.itemId,
+ attackIndex: this.index,
+ field: "damageType",
+ value: damageType,
+ });
+ },
+ "input .LibraryItemAttackBonusInput": _.debounce(function(event, template){
+ Meteor.call("updateLibraryItemAttack", {
+ itemId: template.data.itemId,
+ attackIndex: this.index,
+ field: "attackBonus",
+ value: event.currentTarget.value,
+ });
+ }, 300),
+ "input .LibraryItemAttackDamageInput": _.debounce(function(event, template){
+ Meteor.call("updateLibraryItemAttack", {
+ itemId: template.data.itemId,
+ attackIndex: this.index,
+ field: "damage",
+ value: event.currentTarget.value,
+ });
+ }, 300),
+ "input .LibraryItemAttackDetailsInput": _.debounce(function(event, template){
+ Meteor.call("updateLibraryItemAttack", {
+ itemId: template.data.itemId,
+ attackIndex: this.index,
+ field: "details",
+ value: event.currentTarget.value,
+ });
+ }, 300),
+
+ "click .deleteAttack": function (event, template) {
+ Meteor.call("removeLibraryItemAttack", {
+ itemId: template.data.itemId,
+ attackIndex: this.index,
+ });
+ },
+});
diff --git a/app/client/views/library/library.css b/app/client/views/library/library.css
new file mode 100644
index 00000000..731d8036
--- /dev/null
+++ b/app/client/views/library/library.css
@@ -0,0 +1,19 @@
+.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 e22c9a84..b01f46ff 100644
--- a/app/client/views/library/library.html
+++ b/app/client/views/library/library.html
@@ -1,26 +1,32 @@
-
+
-
- Library
+
+ Item Library
+
-
+
{{> itemLibrary}}
- {{! {{> spellLibrary}} }}
-
+
+
+
diff --git a/app/client/views/library/library.js b/app/client/views/library/library.js
new file mode 100644
index 00000000..70d0e89d
--- /dev/null
+++ b/app/client/views/library/library.js
@@ -0,0 +1,29 @@
+const librarySubs = new SubsManager();
+
+Template.library.onCreated(function(){
+ this.selectedTab = new ReactiveVar("0");
+});
+
+Template.library.helpers({
+ selectedTab(){
+ return Template.instance().selectedTab.get();
+ },
+});
+
+Template.library.events({
+ "iron-select #libraryTabs": function(event, instance){
+ instance.selectedTab.set(event.target.selected);
+ },
+ "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-header[data-id='${libraryId}']`),
+ });
+ },
+})
diff --git a/app/client/views/library/libraryDialog/libraryDialog.html b/app/client/views/library/libraryDialog/libraryDialog.html
new file mode 100644
index 00000000..3fc83637
--- /dev/null
+++ b/app/client/views/library/libraryDialog/libraryDialog.html
@@ -0,0 +1,58 @@
+
+
+
+ {{library.name}}
+
+
+
+
+
+
diff --git a/app/client/views/library/libraryDialog/libraryDialog.js b/app/client/views/library/libraryDialog/libraryDialog.js
new file mode 100644
index 00000000..6c22b871
--- /dev/null
+++ b/app/client/views/library/libraryDialog/libraryDialog.js
@@ -0,0 +1,95 @@
+Template.libraryDialog.onCreated(function(){
+ this.userId = new ReactiveVar();
+ this.autorun(() => {
+ var library = Libraries.findOne(Template.currentData().libraryId, {
+ fields: {readers: 1, writers: 1, owner: 1}
+ });
+ if (!library) return;
+ this.subscribe("userNames", _.union(library.readers, library.writers, [library.owner]));
+ });
+});
+
+Template.libraryDialog.helpers({
+ library(){
+ return Libraries.findOne(this.libraryId);
+ },
+ readers: function(){
+ var library = Libraries.findOne(this.libraryId, {fields: {readers: 1}});
+ return library && library.readers;
+ },
+ writers: function(){
+ var library = Libraries.findOne(this.libraryId, {fields: {writers: 1}});
+ return library && library.writers
+ },
+ username: function(id){
+ const user = Meteor.users.findOne(id);
+ return user && user.username || "user: " + id;
+ },
+ shareButtonDisabled: function(){
+ return !Template.instance().userId.get();
+ },
+ userFindError: function(){
+ if (!Template.instance().userId.get()){
+ return "User not found";
+ }
+ },
+});
+
+Template.libraryDialog.events({
+ "input #libraryNameInput": _.debounce(function(event){
+ const input = event.currentTarget;
+ var name = input.value;
+ if (!name){
+ input.invalid = true;
+ input.errorMessage = "Name is required";
+ } else {
+ input.invalid = false;
+ Libraries.update(this.libraryId, {
+ $set: {name}
+ }, {
+ removeEmptyStrings: false,
+ trimStrings: false,
+ });
+ }
+ }, 300),
+ "click #deleteButton": function(){
+ Meteor.call("removeLibrary", this.libraryId);
+ popDialogStack();
+ },
+ "input #userNameOrEmailInput":
+ function(event, instance){
+ var userName = instance.find("#userNameOrEmailInput").value;
+ instance.userId.set(undefined);
+ Meteor.call("getUserId", userName, function(err, result) {
+ if (err){
+ console.error(err);
+ } else {
+ console.log(result);
+ instance.userId.set(result);
+ }
+ });
+ },
+ "click #shareButton": function(event, instance){
+ var self = this;
+ var permission = instance.find("#accessLevelMenu").selected;
+ if (!permission) throw "no permission set";
+ var userId = instance.userId.get();
+ if (!userId) return;
+ if (permission === "write"){
+ Libraries.update(self.libraryId, {
+ $addToSet: {writers: userId},
+ $pull: {readers: userId},
+ });
+ } else {
+ Libraries.update(self.libraryId, {
+ $addToSet: {readers: userId},
+ $pull: {writers: userId},
+ });
+ }
+ },
+ "click .deleteShare": function(event, instance) {
+ Libraries.update(instance.data.libraryId, {
+ $pull: {writers: this.id, readers: this.id}
+ });
+ },
+});
diff --git a/app/server/publications/library.js b/app/server/publications/library.js
index 1e6a6441..3ab18ce3 100644
--- a/app/server/publications/library.js
+++ b/app/server/publications/library.js
@@ -23,3 +23,18 @@ Meteor.publish("standardLibrarySpells", function(level){
sort: {name: 1},
});
});
+
+Meteor.publish("customLibraries", function(){
+ userId = this.userId;
+ return Libraries.find({
+ $or: [
+ {readers: userId},
+ {writers: userId},
+ {owner: userId},
+ ],
+ });
+});
+
+Meteor.publish("libraryItems", function(libraryId){
+ return LibraryItems.find({library: libraryId});
+});
diff --git a/app/server/publications/user.js b/app/server/publications/user.js
index ceb648ff..799539fd 100644
--- a/app/server/publications/user.js
+++ b/app/server/publications/user.js
@@ -4,5 +4,6 @@ Meteor.publish("user", function(){
username: 1,
profile: 1,
apiKey: 1,
+ librarySubscriptions: 1,
}});
});