diff --git a/app/imports/api/library/Libraries.js b/app/imports/api/library/Libraries.js
index ad485196..f83c48ae 100644
--- a/app/imports/api/library/Libraries.js
+++ b/app/imports/api/library/Libraries.js
@@ -1,5 +1,6 @@
import schema from '/imports/api/schema.js';
import SharingSchema from '/imports/api/sharing/SharingSchema.js';
+import simpleSchemaMixin from '/imports/api/creature/mixins/simpleSchemaMixin.js';
/**
* Libraries are trees of library nodes where each node represents a character
@@ -23,4 +24,17 @@ LibrarySchema.extend(SharingSchema);
Libraries.attachSchema(LibrarySchema);
export default Libraries;
-export { LibrarySchema };
+
+const insertLibrary = new ValidatedMethod({
+ name: 'Libraries.methods.insert',
+ mixins: [
+ simpleSchemaMixin,
+ ],
+ schema: LibrarySchema.omit('owner'),
+ run(library) {
+ library.owner = this.userId;
+ return Libraries.insert(library);
+ },
+});
+
+export { LibrarySchema, insertLibrary };
diff --git a/app/imports/api/users/Users.js b/app/imports/api/users/Users.js
index dd4cd049..fe7a9069 100644
--- a/app/imports/api/users/Users.js
+++ b/app/imports/api/users/Users.js
@@ -10,21 +10,21 @@ const userSchema = schema({
type: Array,
optional: true,
},
- "emails.$": {
+ 'emails.$': {
type: Object,
},
- "emails.$.address": {
+ 'emails.$.address': {
type: String,
regEx: SimpleSchema.RegEx.Email,
},
- "emails.$.verified": {
+ 'emails.$.verified': {
type: Boolean,
},
registered_emails: {
type: Array,
optional: true,
},
- "registered_emails.$": {
+ 'registered_emails.$': {
type: Object,
blackbox: true,
},
@@ -40,7 +40,7 @@ const userSchema = schema({
type: Array,
optional: true,
},
- "roles.$": {
+ 'roles.$': {
type: String
},
// In order to avoid an 'Exception in setInterval callback' from Meteor
@@ -57,12 +57,20 @@ const userSchema = schema({
type: Boolean,
optional: true,
},
+ subscribedLibraries: {
+ type: Array,
+ defaultValue: [],
+ max: 100,
+ },
+ 'subscribedLibraries.$': {
+ type: String,
+ },
});
Meteor.users.attachSchema(userSchema);
Meteor.users.generateApiKey = new ValidatedMethod({
- name: "Users.methods.generateApiKey",
+ name: 'Users.methods.generateApiKey',
validate: null,
run(){
if(Meteor.isClient) return;
@@ -75,7 +83,7 @@ Meteor.users.generateApiKey = new ValidatedMethod({
});
Meteor.users.setDarkMode = new ValidatedMethod({
- name: "Users.methods.setDarkMode",
+ name: 'Users.methods.setDarkMode',
validate: new SimpleSchema({
darkMode: { type: Boolean },
}).validator(),
@@ -86,7 +94,7 @@ Meteor.users.setDarkMode = new ValidatedMethod({
});
Meteor.users.sendVerificationEmail = new ValidatedMethod({
- name: "Users.methods.sendVerificationEmail",
+ name: 'Users.methods.sendVerificationEmail',
validate: schema({
userId:{
type: String,
@@ -100,12 +108,12 @@ Meteor.users.sendVerificationEmail = new ValidatedMethod({
userId = this.userId || userId;
let user = Meteor.users.findOne();
if (!user) {
- throw new Meteor.Error("User not found",
- "Can't send a validation email to a user that does not exist");
+ throw new Meteor.Error('User not found',
+ 'Can\'t send a validation email to a user that does not exist');
}
if (!_.some(user.emails, email => email.address === address)) {
- throw new Meteor.Error("Email address not found",
- "The specified email address wasn't found on this user account");
+ throw new Meteor.Error('Email address not found',
+ 'The specified email address wasn\'t found on this user account');
}
Accounts.sendVerificationEmail(this.userId, address);
}
diff --git a/app/imports/server/publications/library.js b/app/imports/server/publications/library.js
index e8089567..a2981ecc 100644
--- a/app/imports/server/publications/library.js
+++ b/app/imports/server/publications/library.js
@@ -1,23 +1,23 @@
-import Libraries from "/imports/api/library/Libraries.js"
+import Libraries from '/imports/api/library/Libraries.js';
const standardLibraryIds = [
- "SRDLibraryGA3XWsd",
+ 'SRDLibraryGA3XWsd',
];
-Meteor.publish("standardLibraries", function(){
+Meteor.publish('standardLibraries', function(){
return Libraries.find({_id: {$in: standardLibraryIds}});
});
-Meteor.publish("standardLibraryItems", function(categoryKey){
+Meteor.publish('standardLibraryItems', function(categoryKey){
return LibraryItems.find({
library: {$in: standardLibraryIds},
- "settings.category": categoryKey,
+ 'settings.category': categoryKey,
}, {
sort: {name: 1},
});
});
-Meteor.publish("standardLibrarySpells", function(level){
+Meteor.publish('standardLibrarySpells', function(level){
return LibrarySpells.find({
library: {$in: standardLibraryIds},
level,
@@ -25,3 +25,17 @@ Meteor.publish("standardLibrarySpells", function(level){
sort: {name: 1},
});
});
+
+Meteor.publish('libraries', function(){
+ const user = Meteor.user();
+ const userId = user && user._id;
+ const subs = user && user.subscribedLibraries || [];
+ return Libraries.find({
+ $or: [
+ {owner: userId},
+ {writers: userId},
+ {readers: userId},
+ {_id: {$in: subs}},
+ ]
+ });
+});
diff --git a/app/imports/ui/components/Sidebar.vue b/app/imports/ui/components/Sidebar.vue
index 9fdc7b4e..f948d63d 100644
--- a/app/imports/ui/components/Sidebar.vue
+++ b/app/imports/ui/components/Sidebar.vue
@@ -5,7 +5,7 @@
{{userName}}
- settings
+ settings
Account Settings
@@ -82,6 +82,7 @@
return [
{title: "Home", icon: "home", to: "/"},
{title: "Creatures", icon: "group", to: "/characterList", vif: Meteor.userId()},
+ {title: "Libraries", icon: "book", to: "/library", vif: Meteor.userId()},
{title: "Send Feedback", icon: "bug_report", to: "/feedback"},
{title: "Patreon", icon: "", href: "https://www.patreon.com/dicecloud"},
{title: "Github", icon: "", href: "https://github.com/ThaumRystra/DiceCloud1"},
diff --git a/app/imports/ui/components/global/SmartInput.js b/app/imports/ui/components/global/SmartInput.js
index e24e402c..d0574f0d 100644
--- a/app/imports/ui/components/global/SmartInput.js
+++ b/app/imports/ui/components/global/SmartInput.js
@@ -18,7 +18,7 @@ export default {
dirty: false,
safeValue: this.value,
inputValue: this.value,
- }},
+ };},
props: {
value: [String, Number],
debounceTime: {
diff --git a/app/imports/ui/dialogStack/DialogComponentIndex.js b/app/imports/ui/dialogStack/DialogComponentIndex.js
index be78d4e2..4f022a5d 100644
--- a/app/imports/ui/dialogStack/DialogComponentIndex.js
+++ b/app/imports/ui/dialogStack/DialogComponentIndex.js
@@ -3,6 +3,7 @@ import AttributeDialogContainer from '/imports/ui/creature/properties/attributes
import AttributeCreationDialog from '/imports/ui/creature/properties/attributes/AttributeCreationDialog.vue';
import FeatureCreationDialog from '/imports/ui/creature/properties/features/FeatureCreationDialog.vue';
import FeatureDialogContainer from '/imports/ui/creature/properties/features/FeatureDialogContainer.vue';
+import LibraryCreationDialog from '/imports/ui/library/LibraryCreationDialog.vue';
import SkillDialogContainer from '/imports/ui/creature/properties/skills/SkillDialogContainer.vue';
export default {
@@ -11,5 +12,6 @@ export default {
AttributeCreationDialog,
FeatureCreationDialog,
FeatureDialogContainer,
+ LibraryCreationDialog,
SkillDialogContainer,
};
diff --git a/app/imports/ui/library/LibraryCreationDialog.vue b/app/imports/ui/library/LibraryCreationDialog.vue
new file mode 100644
index 00000000..d5b2d98f
--- /dev/null
+++ b/app/imports/ui/library/LibraryCreationDialog.vue
@@ -0,0 +1,53 @@
+
+
+
+
+ New Library
+
+
+
+
+
+
+
+
+ Insert Library
+
+
+
+
+
+
+
+
diff --git a/app/imports/ui/pages/Libraries.vue b/app/imports/ui/pages/Libraries.vue
new file mode 100644
index 00000000..db067767
--- /dev/null
+++ b/app/imports/ui/pages/Libraries.vue
@@ -0,0 +1,71 @@
+
+
+ Libraries
+
+
+
+
+
+ {{library.name}}
+
+
+
+
+
+ You aren't subscribed to any libraries :O
+
+
+
+
+
+
+ add
+
+
+
+
+
+
+
diff --git a/app/imports/ui/router.js b/app/imports/ui/router.js
index 682978ce..d5de3fa5 100644
--- a/app/imports/ui/router.js
+++ b/app/imports/ui/router.js
@@ -1,13 +1,14 @@
import { RouterFactory, nativeScrollBehavior } from 'meteor/akryum:vue-router2';
-import Vue from "vue";
+import Vue from 'vue';
// Components
import Home from '/imports/ui/pages/Home.vue';
-import CharacterList from "/imports/ui/pages/CharacterList.vue";
-import CharacterSheetPage from "/imports/ui/pages/CharacterSheetPage.vue";
-import SignIn from "/imports/ui/pages/SignIn.vue" ;
-import Register from "/imports/ui/pages/Register.vue" ;
-import Account from "/imports/ui/pages/Account.vue" ;
+import CharacterList from '/imports/ui/pages/CharacterList.vue';
+import Libraries from '/imports/ui/pages/Libraries.vue';
+import CharacterSheetPage from '/imports/ui/pages/CharacterSheetPage.vue';
+import SignIn from '/imports/ui/pages/SignIn.vue' ;
+import Register from '/imports/ui/pages/Register.vue' ;
+import Account from '/imports/ui/pages/Account.vue' ;
// Not found
import NotFound from '/imports/ui/pages/NotFound.vue';
@@ -27,22 +28,25 @@ RouterFactory.configure(factory => {
name: 'home',
component: Home,
},{
- path: "/characterList",
+ path: '/characterList',
component: CharacterList,
},{
- path: "/character/:id/:urlName",
+ path: '/library',
+ component: Libraries,
+ },{
+ path: '/character/:id/:urlName',
component: CharacterSheetPage,
},{
- path: "/character/:id",
+ path: '/character/:id',
component: CharacterSheetPage,
},{
- path: "/sign-in",
+ path: '/sign-in',
component: SignIn,
},{
- path: "/register",
+ path: '/register',
component: Register,
},{
- path: "/account",
+ path: '/account',
component: Account,
},
]);
@@ -61,7 +65,7 @@ RouterFactory.configure(factory => {
component: StoryBook,
}, {
path: '/icon-admin',
- name: "iconAdmin",
+ name: 'iconAdmin',
component: IconAdmin,
},
]);
diff --git a/app/imports/ui/styles/inheritBackgrounds.css b/app/imports/ui/styles/inheritBackgrounds.css
new file mode 100644
index 00000000..f8c64dfb
--- /dev/null
+++ b/app/imports/ui/styles/inheritBackgrounds.css
@@ -0,0 +1,14 @@
+/**
+ * Some componets are used as targets for dialog animations often, and thus
+ * require a background color. Inheriting the color from the nearest ancestor
+ * that is known to have a background ensures that the background is
+ * consistent for both light and dark themes
+**/
+
+.v-list > div {
+ background-color: inherit;
+}
+
+.v-list > div > .v-list__tile {
+ background-color: inherit;
+}
diff --git a/app/imports/ui/styles/stylesIndex.js b/app/imports/ui/styles/stylesIndex.js
index 39a0ca67..bf8bcfe9 100644
--- a/app/imports/ui/styles/stylesIndex.js
+++ b/app/imports/ui/styles/stylesIndex.js
@@ -1 +1,2 @@
-import "./speedDial.css";
+import './speedDial.css';
+import './inheritBackgrounds.css';