diff --git a/app/client/head.html b/app/client/head.html index 85ef16df..ba29f029 100644 --- a/app/client/head.html +++ b/app/client/head.html @@ -2,38 +2,38 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + diff --git a/app/imports/api/creature/creatureFolders/CreatureFolders.js b/app/imports/api/creature/creatureFolders/CreatureFolders.js index 56e3fd69..dc411ec6 100644 --- a/app/imports/api/creature/creatureFolders/CreatureFolders.js +++ b/app/imports/api/creature/creatureFolders/CreatureFolders.js @@ -8,7 +8,7 @@ let creatureFolderSchema = new SimpleSchema({ type: String, trim: false, optional: true, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, creatures: { type: Array, @@ -21,16 +21,16 @@ let creatureFolderSchema = new SimpleSchema({ owner: { type: String, regEx: SimpleSchema.RegEx.Id, - index: 1, + index: 1, + }, + archived: { + type: Boolean, + optional: true, + }, + order: { + type: Number, + defaultValue: 0, }, - archived: { - type: Boolean, - optional: true, - }, - order: { - type: Number, - defaultValue: 0, - }, }); CreatureFolders.attachSchema(creatureFolderSchema); diff --git a/app/imports/api/creature/creatureProperties/CreatureProperties.js b/app/imports/api/creature/creatureProperties/CreatureProperties.js index e4cc728e..ff301a79 100644 --- a/app/imports/api/creature/creatureProperties/CreatureProperties.js +++ b/app/imports/api/creature/creatureProperties/CreatureProperties.js @@ -18,23 +18,23 @@ let CreaturePropertySchema = new SimpleSchema({ type: String, optional: true, }, - type: { + type: { type: String, allowedValues: Object.keys(propertySchemasIndex), }, - tags: { - type: Array, - defaultValue: [], + tags: { + type: Array, + defaultValue: [], maxCount: STORAGE_LIMITS.tagCount, - }, - 'tags.$': { - type: String, + }, + 'tags.$': { + type: String, max: STORAGE_LIMITS.tagLength, - }, - disabled: { - type: Boolean, - optional: true, - }, + }, + disabled: { + type: Boolean, + optional: true, + }, icon: { type: storedIconsSchema, optional: true, @@ -93,20 +93,20 @@ const DenormalisedOnlyCreaturePropertySchema = new SimpleSchema({ CreaturePropertySchema.extend(DenormalisedOnlyCreaturePropertySchema); -for (let key in propertySchemasIndex){ - let schema = new SimpleSchema({}); - schema.extend(propertySchemasIndex[key]); - schema.extend(CreaturePropertySchema); +for (let key in propertySchemasIndex) { + let schema = new SimpleSchema({}); + schema.extend(propertySchemasIndex[key]); + schema.extend(CreaturePropertySchema); schema.extend(ColorSchema); - schema.extend(ChildSchema); - schema.extend(SoftRemovableSchema); - CreatureProperties.attachSchema(schema, { - selector: {type: key} - }); + schema.extend(ChildSchema); + schema.extend(SoftRemovableSchema); + CreatureProperties.attachSchema(schema, { + selector: { type: key } + }); } export default CreatureProperties; export { DenormalisedOnlyCreaturePropertySchema, - CreaturePropertySchema, + CreaturePropertySchema, }; diff --git a/app/imports/api/creature/creatureProperties/methods/adjustQuantity.js b/app/imports/api/creature/creatureProperties/methods/adjustQuantity.js index 06ca6459..d08c43bb 100644 --- a/app/imports/api/creature/creatureProperties/methods/adjustQuantity.js +++ b/app/imports/api/creature/creatureProperties/methods/adjustQuantity.js @@ -20,33 +20,33 @@ const adjustQuantity = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({_id, operation, value}) { + run({ _id, operation, value }) { // Permissions - let property = CreatureProperties.findOne(_id); + let property = CreatureProperties.findOne(_id); let rootCreature = getRootCreatureAncestor(property); - assertEditPermission(rootCreature, this.userId); + assertEditPermission(rootCreature, this.userId); // Do work - adjustQuantityWork({property, operation, value}); + adjustQuantityWork({ property, operation, value }); }, }); -export function adjustQuantityWork({property, operation, value}){ +export function adjustQuantityWork({ property, operation, value }) { // Check if property has quantity let schema = CreatureProperties.simpleSchema(property); - if (!schema.allowsKey('quantity')){ + if (!schema.allowsKey('quantity')) { throw new Meteor.Error( 'Adjust quantity failed', `Property of type "${property.type}" doesn't have a quantity` ); } - if (operation === 'set'){ + if (operation === 'set') { CreatureProperties.update(property._id, { - $set: {quantity: value, dirty: true} + $set: { quantity: value, dirty: true } }, { selector: property }); - } else if (operation === 'increment'){ + } else if (operation === 'increment') { // value here is 'damage' value = -value; let currentQuantity = property.quantity; diff --git a/app/imports/api/creature/creatureProperties/methods/damageProperty.js b/app/imports/api/creature/creatureProperties/methods/damageProperty.js index 075aa34f..507d82bd 100644 --- a/app/imports/api/creature/creatureProperties/methods/damageProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/damageProperty.js @@ -22,7 +22,7 @@ const damageProperty = new ValidatedMethod({ timeInterval: 5000, }, run({ _id, operation, value }) { - + // Get action context let prop = CreatureProperties.findOne(_id); if (!prop) throw new Meteor.Error( @@ -30,17 +30,17 @@ const damageProperty = new ValidatedMethod({ ); const creatureId = prop.ancestors[0].id; const actionContext = new ActionContext(creatureId, [creatureId], this); - - // Check permissions + + // Check permissions assertEditPermission(actionContext.creature, this.userId); - // Check if property can take damage - let schema = CreatureProperties.simpleSchema(prop); - if (!schema.allowsKey('damage')){ - throw new Meteor.Error( - 'Damage property failed', - `Property of type "${prop.type}" can't be damaged` - ); + // Check if property can take damage + let schema = CreatureProperties.simpleSchema(prop); + if (!schema.allowsKey('damage')) { + throw new Meteor.Error( + 'Damage property failed', + `Property of type "${prop.type}" can't be damaged` + ); } // Replace the prop by its actionContext counterpart if possible @@ -50,9 +50,9 @@ const damageProperty = new ValidatedMethod({ prop = actionContextProp; } } - + const result = damagePropertyWork({ prop, operation, value, actionContext }); - + // Insert the log actionContext.writeLog(); return result; @@ -86,7 +86,7 @@ export function damagePropertyWork({ prop, operation, value, actionContext }) { } let damage, newValue, increment; - if (operation === 'set'){ + if (operation === 'set') { const total = prop.total || 0; // Set represents what we want the value to be after damage // So we need the actual damage to get to that value @@ -105,7 +105,7 @@ export function damagePropertyWork({ prop, operation, value, actionContext }) { // Also write it straight to the prop so that it is updated in the actionContext prop.damage = damage; prop.value = newValue; - } else if (operation === 'increment'){ + } else if (operation === 'increment') { let currentValue = prop.value || 0; let currentDamage = prop.damage || 0; increment = value; diff --git a/app/imports/api/creature/creatureProperties/methods/duplicateProperty.js b/app/imports/api/creature/creatureProperties/methods/duplicateProperty.js index 3e640714..5a8c84fe 100644 --- a/app/imports/api/creature/creatureProperties/methods/duplicateProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/duplicateProperty.js @@ -5,12 +5,12 @@ import CreatureProperties from '/imports/api/creature/creatureProperties/Creatur import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; import { - setLineageOfDocs, - renewDocIds + setLineageOfDocs, + renewDocIds } from '/imports/api/parenting/parenting.js'; import { reorderDocs } from '/imports/api/parenting/order.js'; var snackbar; -if (Meteor.isClient){ +if (Meteor.isClient) { snackbar = require( '/imports/ui/components/snackbars/SnackbarQueue.js' ).snackbar @@ -31,7 +31,7 @@ const duplicateProperty = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({_id}) { + run({ _id }) { let property = CreatureProperties.findOne(_id); let creature = getRootCreatureAncestor(property); @@ -44,17 +44,17 @@ const duplicateProperty = new ValidatedMethod({ // Get all the descendants let nodes = CreatureProperties.find({ - 'ancestors.id': _id, - removed: {$ne: true}, - }, { + 'ancestors.id': _id, + removed: { $ne: true }, + }, { limit: DUPLICATE_CHILDREN_LIMIT + 1, - sort: {order: 1}, + sort: { order: 1 }, }).fetch(); // Alert the user if the limit was hit - if (nodes.length > DUPLICATE_CHILDREN_LIMIT){ + if (nodes.length > DUPLICATE_CHILDREN_LIMIT) { nodes.pop(); - if (Meteor.isClient){ + if (Meteor.isClient) { snackbar({ text: `Only the first ${DUPLICATE_CHILDREN_LIMIT} children were duplicated`, }); @@ -63,25 +63,25 @@ const duplicateProperty = new ValidatedMethod({ // re-map all the ancestors setLineageOfDocs({ - docArray: nodes, - newAncestry : [ + docArray: nodes, + newAncestry: [ ...property.ancestors, - {id: propertyId, collection: 'creatureProperties'} + { id: propertyId, collection: 'creatureProperties' } ], - oldParent : {id: _id, collection: 'creatureProperties'}, - }); + oldParent: { id: _id, collection: 'creatureProperties' }, + }); // Give the docs new IDs without breaking internal references - renewDocIds({docArray: nodes}); + renewDocIds({ docArray: nodes }); // Order the root node property.order += 0.5; - + // Mark the sheet as needing recompute property.dirty = true; // Insert the properties - CreatureProperties.batchInsert([property, ...nodes]); + CreatureProperties.batchInsert([property, ...nodes]); // Tree structure changed by inserts, reorder the tree reorderDocs({ diff --git a/app/imports/api/creature/creatureProperties/methods/equipItem.js b/app/imports/api/creature/creatureProperties/methods/equipItem.js index a8bbb911..671908b3 100644 --- a/app/imports/api/creature/creatureProperties/methods/equipItem.js +++ b/app/imports/api/creature/creatureProperties/methods/equipItem.js @@ -10,8 +10,8 @@ import getParentRefByTag from '/imports/api/creature/creatureProperties/methods/ // Equipping or unequipping an item will also change its parent const equipItem = new ValidatedMethod({ name: 'creatureProperties.equip', - validate({_id, equipped}){ - if (!_id) throw new Meteor.Error('No _id', '_id is required'); + validate({ _id, equipped }) { + if (!_id) throw new Meteor.Error('No _id', '_id is required'); if (equipped !== true && equipped !== false) { throw new Meteor.Error('No equipped', 'equipped is required to be true or false'); } @@ -21,20 +21,20 @@ const equipItem = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({_id, equipped}) { + run({ _id, equipped }) { let item = CreatureProperties.findOne(_id); if (item.type !== 'item') throw new Meteor.Error('wrong type', - 'Equip and unequip can only be performed on items'); + 'Equip and unequip can only be performed on items'); let creature = getRootCreatureAncestor(item); assertEditPermission(creature, this.userId); CreatureProperties.update(_id, { $set: { equipped, dirty: true }, }, { - selector: {type: 'item'}, - }); + selector: { type: 'item' }, + }); let tag = equipped ? BUILT_IN_TAGS.equipment : BUILT_IN_TAGS.carried; let parentRef = getParentRefByTag(creature._id, tag); - if (!parentRef) parentRef = {id: creature._id, collection: 'creatures'}; + if (!parentRef) parentRef = { id: creature._id, collection: 'creatures' }; organizeDoc.call({ docRef: { diff --git a/app/imports/api/creature/creatureProperties/methods/flipToggle.js b/app/imports/api/creature/creatureProperties/methods/flipToggle.js index df563cdc..dbd814ff 100644 --- a/app/imports/api/creature/creatureProperties/methods/flipToggle.js +++ b/app/imports/api/creature/creatureProperties/methods/flipToggle.js @@ -6,24 +6,24 @@ import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/ge const flipToggle = new ValidatedMethod({ name: 'creatureProperties.flipToggle', - validate({_id}){ - if (!_id) throw new Meteor.Error('No _id', '_id is required'); + validate({ _id }) { + if (!_id) throw new Meteor.Error('No _id', '_id is required'); }, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id}) { + run({ _id }) { // Permission let property = CreatureProperties.findOne(_id, { - fields: {type: 1, ancestors: 1, enabled: 1, disabled: 1} + fields: { type: 1, ancestors: 1, enabled: 1, disabled: 1 } }); - if (property.type !== 'toggle'){ + if (property.type !== 'toggle') { throw new Meteor.Error('wrong property', 'This method can only be applied to toggles'); } - if (!property.enabled && !property.disabled){ + if (!property.enabled && !property.disabled) { throw new Meteor.Error('Computed toggle', 'Can\'t flip a toggle that is computed') } @@ -32,13 +32,15 @@ const flipToggle = new ValidatedMethod({ // Invert the current value, disabled is the canonical store of value const currentValue = !property.disabled; - CreatureProperties.update(_id, {$set: { - enabled: !currentValue, - disabled: currentValue, - dirty: true, - }}, { - selector: {type: 'toggle'}, - }); + CreatureProperties.update(_id, { + $set: { + enabled: !currentValue, + disabled: currentValue, + dirty: true, + } + }, { + selector: { type: 'toggle' }, + }); }, }); diff --git a/app/imports/api/creature/creatureProperties/methods/insertProperty.js b/app/imports/api/creature/creatureProperties/methods/insertProperty.js index 5d3567b0..2d872868 100644 --- a/app/imports/api/creature/creatureProperties/methods/insertProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/insertProperty.js @@ -12,7 +12,7 @@ import { getHighestOrder } from '/imports/api/parenting/order.js'; const insertProperty = new ValidatedMethod({ name: 'creatureProperties.insert', - validate: new SimpleSchema({ + validate: new SimpleSchema({ creatureProperty: { type: Object, blackbox: true, @@ -24,25 +24,25 @@ const insertProperty = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({creatureProperty, parentRef}) { + run({ creatureProperty, parentRef }) { // get the new ancestry for the properties - let {parentDoc, ancestors} = getAncestry({parentRef}); + let { parentDoc, ancestors } = getAncestry({ parentRef }); - // Check permission to edit + // Check permission to edit let rootCreature; - if (parentRef.collection === 'creatures'){ + if (parentRef.collection === 'creatures') { rootCreature = parentDoc; - } else if (parentRef.collection === 'creatureProperties'){ + } else if (parentRef.collection === 'creatureProperties') { rootCreature = getRootCreatureAncestor(parentDoc); - } else { - throw `${parentRef.collection} is not a valid parent collection` - } + } else { + throw `${parentRef.collection} is not a valid parent collection` + } assertEditPermission(rootCreature, this.userId); creatureProperty.parent = parentRef; creatureProperty.ancestors = ancestors; - return insertPropertyWork({ + return insertPropertyWork({ property: creatureProperty, creature: rootCreature, }); @@ -75,31 +75,31 @@ const insertPropertyAsChildOfTag = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({creatureProperty, creatureId, tag, tagDefaultName}) { + run({ creatureProperty, creatureId, tag, tagDefaultName }) { let parentRef = getParentRefByTag(creatureId, tag); - if (!parentRef){ + if (!parentRef) { // Use the creature as the parent and mark that we need to insert the folder first later var insertFolderFirst = true; - parentRef = {id: creatureId, collection: 'creatures'}; + parentRef = { id: creatureId, collection: 'creatures' }; } // get the new ancestry for the properties - let {parentDoc, ancestors} = getAncestry({parentRef}); + let { parentDoc, ancestors } = getAncestry({ parentRef }); // Check permission to edit let rootCreature; - if (parentRef.collection === 'creatures'){ + if (parentRef.collection === 'creatures') { rootCreature = parentDoc; - } else if (parentRef.collection === 'creatureProperties'){ + } else if (parentRef.collection === 'creatureProperties') { rootCreature = getRootCreatureAncestor(parentDoc); - } else { - throw `${parentRef.collection} is not a valid parent collection` - } + } else { + throw `${parentRef.collection} is not a valid parent collection` + } assertEditPermission(rootCreature, this.userId); // Add the folder first if we need to - if (insertFolderFirst){ + if (insertFolderFirst) { let order = getHighestOrder({ collection: CreatureProperties, ancestorId: parentRef.id, @@ -113,7 +113,7 @@ const insertPropertyAsChildOfTag = new ValidatedMethod({ order, }); // Make the folder our new parent - let newParentRef = {id, collection: 'creatureProperties'}; + let newParentRef = { id, collection: 'creatureProperties' }; ancestors = [parentRef, newParentRef]; parentRef = newParentRef; creatureProperty.order = order + 1; @@ -122,14 +122,14 @@ const insertPropertyAsChildOfTag = new ValidatedMethod({ creatureProperty.parent = parentRef; creatureProperty.ancestors = ancestors; - return insertPropertyWork({ + return insertPropertyWork({ property: creatureProperty, creature: rootCreature, }); }, }); -export function insertPropertyWork({property, creature}){ +export function insertPropertyWork({ property, creature }) { delete property._id; property.dirty = true; let _id = CreatureProperties.insert(property); diff --git a/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js b/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js index 10de2b4a..641a9cfb 100644 --- a/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js +++ b/app/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js @@ -7,57 +7,57 @@ import { RefSchema } from '/imports/api/parenting/ChildSchema.js'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js'; import { - setLineageOfDocs, - getAncestry, - renewDocIds + setLineageOfDocs, + getAncestry, + renewDocIds } from '/imports/api/parenting/parenting.js'; import { reorderDocs } from '/imports/api/parenting/order.js'; import { setDocToLastOrder } from '/imports/api/parenting/order.js'; import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js'; const insertPropertyFromLibraryNode = new ValidatedMethod({ - name: 'creatureProperties.insertPropertyFromLibraryNode', - validate: new SimpleSchema({ + name: 'creatureProperties.insertPropertyFromLibraryNode', + validate: new SimpleSchema({ nodeIds: { type: Array, max: 20, }, - 'nodeIds.$': { - type: String, - regEx: SimpleSchema.RegEx.Id, - }, - parentRef: { - type: RefSchema, - }, + 'nodeIds.$': { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + parentRef: { + type: RefSchema, + }, order: { type: Number, optional: true, }, - }).validator(), + }).validator(), mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({nodeIds, parentRef, order}) { - // get the new ancestry for the properties - let {parentDoc, ancestors} = getAncestry({parentRef}); + run({ nodeIds, parentRef, order }) { + // get the new ancestry for the properties + let { parentDoc, ancestors } = getAncestry({ parentRef }); - // Check permission to edit + // Check permission to edit let rootCreature; - if (parentRef.collection === 'creatures'){ + if (parentRef.collection === 'creatures') { rootCreature = parentDoc; - } else if (parentRef.collection === 'creatureProperties'){ + } else if (parentRef.collection === 'creatureProperties') { rootCreature = getRootCreatureAncestor(parentDoc); - } else { - throw `${parentRef.collection} is not a valid parent collection` - } + } else { + throw `${parentRef.collection} is not a valid parent collection` + } assertEditPermission(rootCreature, this.userId); // {libraryId: hasViewPermission} //let libraryPermissionMemoir = {}; let node; - nodeIds.forEach(nodeId => { + nodeIds.forEach(nodeId => { // TODO: Check library view permission for each node before starting node = insertPropertyFromNode(nodeId, ancestors, order); }); @@ -70,18 +70,18 @@ const insertPropertyFromLibraryNode = new ValidatedMethod({ collection: CreatureProperties, ancestorId: rootCreature._id, }); - // Return the docId of the last property, the inserted root property - return rootId; - }, + // Return the docId of the last property, the inserted root property + return rootId; + }, }); -function insertPropertyFromNode(nodeId, ancestors, order){ +function insertPropertyFromNode(nodeId, ancestors, order) { // Fetch the library node and its decendents, provided they have not been // removed // TODO: Check permission to read the library this node is in let node = LibraryNodes.findOne({ _id: nodeId, - removed: {$ne: true}, + removed: { $ne: true }, }); if (!node) { if (Meteor.isClient) return; @@ -95,7 +95,7 @@ function insertPropertyFromNode(nodeId, ancestors, order){ let oldParent = node.parent; let nodes = LibraryNodes.find({ 'ancestors.id': nodeId, - removed: {$ne: true}, + removed: { $ne: true }, }).fetch(); // Convert all references into actual nodes @@ -118,11 +118,11 @@ function insertPropertyFromNode(nodeId, ancestors, order){ // Give the docs new IDs without breaking internal references renewDocIds({ docArray: nodes, - collectionMap: {'libraryNodes': 'creatureProperties'} + collectionMap: { 'libraryNodes': 'creatureProperties' } }); // Order the root node - if (order === undefined){ + if (order === undefined) { setDocToLastOrder({ collection: CreatureProperties, doc: node, @@ -139,7 +139,7 @@ function insertPropertyFromNode(nodeId, ancestors, order){ return node; } -function storeLibraryNodeReferences(nodes){ +function storeLibraryNodeReferences(nodes) { nodes.forEach(node => { if (node.libraryNodeId) return; node.libraryNodeId = node._id; @@ -154,7 +154,7 @@ function dirtyNodes(nodes) { // Covert node references into actual nodes // TODO: check permissions for each library a reference node references -function reifyNodeReferences(nodes, visitedRefs = new Set(), depth = 0){ +function reifyNodeReferences(nodes, visitedRefs = new Set(), depth = 0) { depth += 1; // New nodes added this function let newNodes = []; @@ -165,9 +165,9 @@ function reifyNodeReferences(nodes, visitedRefs = new Set(), depth = 0){ if (node.type !== 'reference') return true; // We have gone too deep, keep the reference node as an error - if (depth >= 10){ + if (depth >= 10) { if (Meteor.isClient) console.warn('Reference depth limit exceeded'); - node.cache = {error: 'Reference depth limit exceeded'}; + node.cache = { error: 'Reference depth limit exceeded' }; return true; } @@ -177,17 +177,17 @@ function reifyNodeReferences(nodes, visitedRefs = new Set(), depth = 0){ referencedNode.order = node.order; // We are definitely replacing this node, so add it to the list visitedRefs.add(node._id); - } catch (e){ - node.cache = {error: e.reason || e.message || e.toString()}; + } catch (e) { + node.cache = { error: e.reason || e.message || e.toString() }; return true; } // Get all the descendants of the referenced node let descendents = LibraryNodes.find({ 'ancestors.id': referencedNode._id, - removed: {$ne: true}, + removed: { $ne: true }, }, { - sort: {order: 1}, + sort: { order: 1 }, }).fetch(); // We are adding the referenced node and its descendants @@ -195,20 +195,20 @@ function reifyNodeReferences(nodes, visitedRefs = new Set(), depth = 0){ // re-map all the ancestors to parent the new sub-tree into our existing // node tree - setLineageOfDocs({ - docArray: addedNodes, - newAncestry: node.ancestors, - oldParent: referencedNode.parent, - }); + setLineageOfDocs({ + docArray: addedNodes, + newAncestry: node.ancestors, + oldParent: referencedNode.parent, + }); // Filter all the looped references addedNodes = addedNodes.filter(addedNode => { // Add all non-reference nodes - if (addedNode.type !== 'reference'){ + if (addedNode.type !== 'reference') { return true; } // If this exact reference has already been resolved before, filter it out - if (visitedRefs.has(addedNode._id)){ + if (visitedRefs.has(addedNode._id)) { return false; } else { // Otherwise mark it as visited, and keep it diff --git a/app/imports/api/creature/creatureProperties/methods/pullFromProperty.js b/app/imports/api/creature/creatureProperties/methods/pullFromProperty.js index 3d8f99ea..4dd8245e 100644 --- a/app/imports/api/creature/creatureProperties/methods/pullFromProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/pullFromProperty.js @@ -5,28 +5,28 @@ import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; const pullFromProperty = new ValidatedMethod({ - name: 'creatureProperties.pull', - validate: null, + name: 'creatureProperties.pull', + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id, path, itemId}){ + run({ _id, path, itemId }) { // Permissions - let property = CreatureProperties.findOne(_id); + let property = CreatureProperties.findOne(_id); let rootCreature = getRootCreatureAncestor(property); assertEditPermission(rootCreature, this.userId); // Do work - CreatureProperties.update(_id, { + CreatureProperties.update(_id, { $pull: { [path.join('.')]: { _id: itemId } }, $set: { dirty: true } - }, { - selector: {type: property.type}, - getAutoValues: false, - }); - } + }, { + selector: { type: property.type }, + getAutoValues: false, + }); + } }); export default pullFromProperty; diff --git a/app/imports/api/creature/creatureProperties/methods/pushToProperty.js b/app/imports/api/creature/creatureProperties/methods/pushToProperty.js index 0ec4719c..95735d9b 100644 --- a/app/imports/api/creature/creatureProperties/methods/pushToProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/pushToProperty.js @@ -6,16 +6,16 @@ import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/ge import { get } from 'lodash'; const pushToProperty = new ValidatedMethod({ - name: 'creatureProperties.push', - validate: null, + name: 'creatureProperties.push', + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id, path, value}){ + run({ _id, path, value }) { // Permissions - let property = CreatureProperties.findOne(_id); + let property = CreatureProperties.findOne(_id); let rootCreature = getRootCreatureAncestor(property); assertEditPermission(rootCreature, this.userId); @@ -25,10 +25,10 @@ const pushToProperty = new ValidatedMethod({ let schema = CreatureProperties.simpleSchema(property); let maxCount = schema.get(joinedPath, 'maxCount'); - if (Number.isFinite(maxCount)){ + if (Number.isFinite(maxCount)) { let array = get(property, path); let currentCount = array ? array.length : 0; - if (currentCount >= maxCount){ + if (currentCount >= maxCount) { throw new Meteor.Error( 'Array is full', `Cannot have more than ${maxCount} values` @@ -37,13 +37,13 @@ const pushToProperty = new ValidatedMethod({ } // Do work - CreatureProperties.update(_id, { + CreatureProperties.update(_id, { $push: { [joinedPath]: value }, $set: { dirty: true }, - }, { - selector: {type: property.type}, - }); - } + }, { + selector: { type: property.type }, + }); + } }); export default pushToProperty; diff --git a/app/imports/api/creature/creatureProperties/methods/restoreProperty.js b/app/imports/api/creature/creatureProperties/methods/restoreProperty.js index 02ed7637..9e66448e 100644 --- a/app/imports/api/creature/creatureProperties/methods/restoreProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/restoreProperty.js @@ -7,18 +7,18 @@ import { restore } from '/imports/api/parenting/softRemove.js'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; const restoreProperty = new ValidatedMethod({ - name: 'creatureProperties.restore', - validate: new SimpleSchema({ - _id: SimpleSchema.RegEx.Id - }).validator(), + name: 'creatureProperties.restore', + validate: new SimpleSchema({ + _id: SimpleSchema.RegEx.Id + }).validator(), mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id}){ + run({ _id }) { // Permissions - let property = CreatureProperties.findOne(_id); + let property = CreatureProperties.findOne(_id); let rootCreature = getRootCreatureAncestor(property); assertEditPermission(rootCreature, this.userId); @@ -30,7 +30,7 @@ const restoreProperty = new ValidatedMethod({ $set: { dirty: true } }, }); - } + } }); export default restoreProperty; diff --git a/app/imports/api/creature/creatureProperties/methods/selectAmmoItem.js b/app/imports/api/creature/creatureProperties/methods/selectAmmoItem.js index 4f460287..57bbe6bd 100644 --- a/app/imports/api/creature/creatureProperties/methods/selectAmmoItem.js +++ b/app/imports/api/creature/creatureProperties/methods/selectAmmoItem.js @@ -17,20 +17,20 @@ const selectAmmoItem = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({actionId, itemId, itemConsumedIndex}) { + run({ actionId, itemId, itemConsumedIndex }) { // Permissions - let action = CreatureProperties.findOne(actionId); + let action = CreatureProperties.findOne(actionId); let rootCreature = getRootCreatureAncestor(action); - assertEditPermission(rootCreature, this.userId); + assertEditPermission(rootCreature, this.userId); // Check that this index has a document to edit let itemConsumed = action.resources.itemsConsumed[itemConsumedIndex]; - if (!itemConsumed){ + if (!itemConsumed) { throw new Meteor.Error('Resouce not found', 'Could not set ammo, because the ammo document was not found'); } let itemToLink = CreatureProperties.findOne(itemId); - if (!itemToLink){ + if (!itemToLink) { throw new Meteor.Error('Item not found', 'Could not set ammo: the item was not found'); } diff --git a/app/imports/api/creature/creatureProperties/methods/softRemoveProperty.js b/app/imports/api/creature/creatureProperties/methods/softRemoveProperty.js index 96110e8e..a4240ac7 100644 --- a/app/imports/api/creature/creatureProperties/methods/softRemoveProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/softRemoveProperty.js @@ -7,24 +7,24 @@ import { softRemove } from '/imports/api/parenting/softRemove.js'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; const softRemoveProperty = new ValidatedMethod({ - name: 'creatureProperties.softRemove', - validate: new SimpleSchema({ - _id: SimpleSchema.RegEx.Id - }).validator(), + name: 'creatureProperties.softRemove', + validate: new SimpleSchema({ + _id: SimpleSchema.RegEx.Id + }).validator(), mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id}){ + run({ _id }) { // Permissions - let property = CreatureProperties.findOne(_id); + let property = CreatureProperties.findOne(_id); let rootCreature = getRootCreatureAncestor(property); assertEditPermission(rootCreature, this.userId); // Do work - softRemove({_id, collection: CreatureProperties}); - } + softRemove({ _id, collection: CreatureProperties }); + } }); export default softRemoveProperty; diff --git a/app/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js b/app/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js index d6bf733c..4b606114 100644 --- a/app/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js +++ b/app/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js @@ -6,28 +6,28 @@ import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/ge const updateCreatureProperty = new ValidatedMethod({ name: 'creatureProperties.update', - validate({_id, path}){ - if (!_id) throw new Meteor.Error('No _id', '_id is required'); - // We cannot change these fields with a simple update - switch (path[0]){ - case 'type': + validate({ _id, path }) { + if (!_id) throw new Meteor.Error('No _id', '_id is required'); + // We cannot change these fields with a simple update + switch (path[0]) { + case 'type': case 'order': case 'parent': case 'ancestors': - case 'damage': - throw new Meteor.Error('Permission denied', - 'This property can\'t be updated directly'); - } + case 'damage': + throw new Meteor.Error('Permission denied', + 'This property can\'t be updated directly'); + } }, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id, path, value}) { + run({ _id, path, value }) { // Permission let property = CreatureProperties.findOne(_id, { - fields: {type: 1, ancestors: 1} + fields: { type: 1, ancestors: 1 } }); let rootCreature = getRootCreatureAncestor(property); assertEditPermission(rootCreature, this.userId); @@ -35,14 +35,14 @@ const updateCreatureProperty = new ValidatedMethod({ let pathString = path.join('.'); let modifier; // unset empty values - if (value === null || value === undefined){ - modifier = { $unset: {[pathString]: 1}, $set: { dirty: true } }; + if (value === null || value === undefined) { + modifier = { $unset: { [pathString]: 1 }, $set: { dirty: true } }; } else { - modifier = { $set: {[pathString]: value, dirty: true } }; + modifier = { $set: { [pathString]: value, dirty: true } }; } - CreatureProperties.update(_id, modifier, { - selector: {type: property.type}, - }); + CreatureProperties.update(_id, modifier, { + selector: { type: property.type }, + }); }, }); diff --git a/app/imports/api/creature/creatureProperties/recomputeCreaturesByProperty.js b/app/imports/api/creature/creatureProperties/recomputeCreaturesByProperty.js index cee1237d..a2190860 100644 --- a/app/imports/api/creature/creatureProperties/recomputeCreaturesByProperty.js +++ b/app/imports/api/creature/creatureProperties/recomputeCreaturesByProperty.js @@ -4,9 +4,9 @@ import computeCreature from '/imports/api/engine/computeCreature.js'; * Recomputes all ancestor creatures of this property */ export default function recomputeCreaturesByProperty(property){ - for (let ref of property.ancestors){ - if (ref.collection === 'creatures') { - computeCreature.call(ref.id); - } - } + for (let ref of property.ancestors){ + if (ref.collection === 'creatures') { + computeCreature.call(ref.id); + } + } } diff --git a/app/imports/api/creature/creatures/Creatures.js b/app/imports/api/creature/creatures/Creatures.js index 25ff5021..f13932ee 100644 --- a/app/imports/api/creature/creatures/Creatures.js +++ b/app/imports/api/creature/creatures/Creatures.js @@ -8,21 +8,21 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; let Creatures = new Mongo.Collection('creatures'); let CreatureSettingsSchema = new SimpleSchema({ - //slowed down by carrying too much? - useVariantEncumbrance: { - type: Boolean, - optional: true, - }, - //hide spellcasting tab - hideSpellcasting: { - type: Boolean, - optional: true, - }, - // Swap around the modifier and stat - swapStatAndModifier: { - type: Boolean, - optional: true, - }, + //slowed down by carrying too much? + useVariantEncumbrance: { + type: Boolean, + optional: true, + }, + //hide spellcasting tab + hideSpellcasting: { + type: Boolean, + optional: true, + }, + // Swap around the modifier and stat + swapStatAndModifier: { + type: Boolean, + optional: true, + }, // Hide all the unused stats hideUnusedStats: { type: Boolean, @@ -58,28 +58,28 @@ let CreatureSettingsSchema = new SimpleSchema({ }); let CreatureSchema = new SimpleSchema({ - // Strings - name: { - type: String, - defaultValue: '', - optional: true, + // Strings + name: { + type: String, + defaultValue: '', + optional: true, max: STORAGE_LIMITS.name, - }, - alignment: { - type: String, - optional: true, + }, + alignment: { + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, - gender: { - type: String, - optional: true, + }, + gender: { + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, - picture: { - type: String, - optional: true, + }, + picture: { + type: String, + optional: true, max: STORAGE_LIMITS.url, - }, + }, avatarPicture: { type: String, optional: true, @@ -90,37 +90,37 @@ let CreatureSchema = new SimpleSchema({ allowedLibraries: { type: Array, optional: true, - maxCount: 100, - }, - 'allowedLibraries.$': { - type: String, + maxCount: 100, + }, + 'allowedLibraries.$': { + type: String, regEx: SimpleSchema.RegEx.Id, - }, - allowedLibraryCollections: { - type: Array, + }, + allowedLibraryCollections: { + type: Array, optional: true, - maxCount: 100, - }, - 'allowedLibraryCollections.$': { - type: String, + maxCount: 100, + }, + 'allowedLibraryCollections.$': { + type: String, regEx: SimpleSchema.RegEx.Id, }, - // Mechanics - deathSave: { - type: deathSaveSchema, - defaultValue: {}, - }, + // Mechanics + deathSave: { + type: deathSaveSchema, + defaultValue: {}, + }, // Stats that are computed and denormalised outside of recomputation denormalizedStats: { type: Object, defaultValue: {}, }, // Sum of all XP gained by this character - 'denormalizedStats.xp': { - type: SimpleSchema.Integer, - defaultValue: 0, - }, + 'denormalizedStats.xp': { + type: SimpleSchema.Integer, + defaultValue: 0, + }, // Sum of all levels granted by milestone XP 'denormalizedStats.milestoneLevels': { type: SimpleSchema.Integer, @@ -133,24 +133,24 @@ let CreatureSchema = new SimpleSchema({ }, // Version of computation engine that was last used to compute this creature computeVersion: { - type: String, + type: String, optional: true, - }, - type: { - type: String, - defaultValue: 'pc', - allowedValues: ['pc', 'npc', 'monster'], - }, + }, + type: { + type: String, + defaultValue: 'pc', + allowedValues: ['pc', 'npc', 'monster'], + }, damageMultipliers: { type: Object, - blackbox: true, - defaultValue: {} + blackbox: true, + defaultValue: {} + }, + variables: { + type: Object, + blackbox: true, + defaultValue: {} }, - variables: { - type: Object, - blackbox: true, - defaultValue: {} - }, computeErrors: { type: Array, optional: true, @@ -161,7 +161,7 @@ let CreatureSchema = new SimpleSchema({ 'computeErrors.$.type': { type: String, }, - 'computeErrors.$.details' : { + 'computeErrors.$.details': { type: Object, blackbox: true, optional: true, @@ -178,11 +178,11 @@ let CreatureSchema = new SimpleSchema({ optional: true, }, - // Settings - settings: { - type: CreatureSettingsSchema, - defaultValue: {}, - }, + // Settings + settings: { + type: CreatureSettingsSchema, + defaultValue: {}, + }, }); CreatureSchema.extend(ColorSchema); diff --git a/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js b/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js index 29057f55..05a8e9d6 100644 --- a/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js +++ b/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js @@ -1,7 +1,7 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import Creatures from '/imports/api/creature/creatures/Creatures.js'; -import {assertEditPermission} from '/imports/api/sharing/sharingPermissions.js'; +import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js'; import SimpleSchema from 'simpl-schema'; import simpleSchemaMixin from '/imports/api/creature/mixins/simpleSchemaMixin.js'; @@ -36,8 +36,8 @@ const changeAllowedLibraries = new ValidatedMethod({ numRequests: 10, timeInterval: 5000, }, - run({_id, allowedLibraries, allowedLibraryCollections}) { - let creature = Creatures.findOne(_id); + run({ _id, allowedLibraries, allowedLibraryCollections }) { + let creature = Creatures.findOne(_id); assertEditPermission(creature, this.userId); let $set; if (allowedLibraries) { @@ -48,7 +48,7 @@ const changeAllowedLibraries = new ValidatedMethod({ $set.allowedLibraryCollections = allowedLibraryCollections; } if (!$set) return; - Creatures.update(_id, {$set}); + Creatures.update(_id, { $set }); }, }); @@ -68,7 +68,7 @@ const toggleAllUserLibraries = new ValidatedMethod({ numRequests: 10, timeInterval: 5000, }, - run({_id, value}) { + run({ _id, value }) { if (value) { Creatures.update(_id, { $unset: { @@ -87,4 +87,4 @@ const toggleAllUserLibraries = new ValidatedMethod({ }, }); -export {changeAllowedLibraries, toggleAllUserLibraries}; +export { changeAllowedLibraries, toggleAllUserLibraries }; diff --git a/app/imports/api/creature/creatures/methods/insertCreature.js b/app/imports/api/creature/creatures/methods/insertCreature.js index da72f6ed..c978785b 100644 --- a/app/imports/api/creature/creatures/methods/insertCreature.js +++ b/app/imports/api/creature/creatures/methods/insertCreature.js @@ -51,7 +51,7 @@ const insertCreature = new ValidatedMethod({ allowedLibraries, allowedLibraryCollections, }); - + // Insert experience to get character to starting level if (startingLevel) { insertExperienceForCreature({ @@ -70,7 +70,7 @@ const insertCreature = new ValidatedMethod({ let baseId, rulesetSlot; defaultCharacterProperties(creatureId).forEach(prop => { let id = CreatureProperties.insert(prop); - if (prop.name === 'Ruleset'){ + if (prop.name === 'Ruleset') { baseId = id; rulesetSlot = prop; } @@ -81,7 +81,7 @@ const insertCreature = new ValidatedMethod({ insertDefaultRuleset(creatureId, baseId, userId, rulesetSlot); } - return creatureId; + return creatureId; }, }); @@ -95,7 +95,7 @@ function insertDefaultRuleset(creatureId, baseId, userId, slot) { const ruleset = fillCursor.fetch()[0] insertPropertyFromLibraryNode.call({ nodeIds: [ruleset._id], - parentRef: {id: baseId, collection: 'creatureProperties'}, + parentRef: { id: baseId, collection: 'creatureProperties' }, order: 0.5, }); } diff --git a/app/imports/api/creature/creatures/methods/updateCreature.js b/app/imports/api/creature/creatures/methods/updateCreature.js index 6530ccae..4da290bc 100644 --- a/app/imports/api/creature/creatures/methods/updateCreature.js +++ b/app/imports/api/creature/creatures/methods/updateCreature.js @@ -1,14 +1,14 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import Creatures from '/imports/api/creature/creatures/Creatures.js'; -import {assertEditPermission} from '/imports/api/sharing/sharingPermissions.js'; +import { assertEditPermission } from '/imports/api/sharing/sharingPermissions.js'; const updateCreature = new ValidatedMethod({ name: 'creatures.update', - validate({_id, path}){ - if (!_id) return false; - // Allowed fields - let allowedFields = [ + validate({ _id, path }) { + if (!_id) return false; + // Allowed fields + let allowedFields = [ 'name', 'alignment', 'gender', @@ -17,26 +17,26 @@ const updateCreature = new ValidatedMethod({ 'color', 'settings', ]; - if (!allowedFields.includes(path[0])){ - throw new Meteor.Error('Creatures.methods.update.denied', - 'This field can\'t be updated using this method'); - } + if (!allowedFields.includes(path[0])) { + throw new Meteor.Error('Creatures.methods.update.denied', + 'This field can\'t be updated using this method'); + } }, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id, path, value}) { - let creature = Creatures.findOne(_id); + run({ _id, path, value }) { + let creature = Creatures.findOne(_id); assertEditPermission(creature, this.userId); - if (value === undefined || value === null){ + if (value === undefined || value === null) { Creatures.update(_id, { - $unset: {[path.join('.')]: 1}, + $unset: { [path.join('.')]: 1 }, }); } else { Creatures.update(_id, { - $set: {[path.join('.')]: value}, + $set: { [path.join('.')]: value }, }); } }, diff --git a/app/imports/api/creature/experience/Experiences.js b/app/imports/api/creature/experience/Experiences.js index 58b1aeed..d1c5c527 100644 --- a/app/imports/api/creature/experience/Experiences.js +++ b/app/imports/api/creature/experience/Experiences.js @@ -8,17 +8,17 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; let Experiences = new Mongo.Collection('experiences'); let ExperienceSchema = new SimpleSchema({ - name: { - type: String, - optional: true, + name: { + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, - // The amount of XP this experience gives - xp: { - type: SimpleSchema.Integer, - optional: true, + }, + // The amount of XP this experience gives + xp: { + type: SimpleSchema.Integer, + optional: true, min: 0, - }, + }, // Setting levels instead of value grants whole levels levels: { type: SimpleSchema.Integer, @@ -26,17 +26,17 @@ let ExperienceSchema = new SimpleSchema({ min: 0, index: 1, }, - // The real-world date that it occured, usually sorted by date - date: { - type: Date, - autoValue: function() { - // If the date isn't set, set it to now - if (!this.isSet) { - return new Date(); - } - }, + // The real-world date that it occured, usually sorted by date + date: { + type: Date, + autoValue: function () { + // If the date isn't set, set it to now + if (!this.isSet) { + return new Date(); + } + }, index: 1, - }, + }, creatureId: { type: String, regEx: SimpleSchema.RegEx.Id, @@ -46,8 +46,8 @@ let ExperienceSchema = new SimpleSchema({ Experiences.attachSchema(ExperienceSchema); -const insertExperienceForCreature = function({experience, creatureId, userId}){ - if (experience.xp){ +const insertExperienceForCreature = function ({ experience, creatureId }) { + if (experience.xp) { Creatures.update(creatureId, { $inc: { 'denormalizedStats.xp': experience.xp }, $set: { dirty: true }, @@ -84,16 +84,16 @@ const insertExperience = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({experience, creatureIds}) { + run({ experience, creatureIds }) { let userId = this.userId; if (!userId) { throw new Meteor.Error('Experiences.methods.insert.denied', - 'You need to be logged in to insert an experience'); + 'You need to be logged in to insert an experience'); } let insertedIds = []; creatureIds.forEach(creatureId => { assertEditPermission(creatureId, userId); - let id = insertExperienceForCreature({experience, creatureId, userId}); + let id = insertExperienceForCreature({ experience, creatureId, userId }); insertedIds.push(id); }); return insertedIds; @@ -113,17 +113,17 @@ const removeExperience = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({experienceId}) { + run({ experienceId }) { let userId = this.userId; if (!userId) { throw new Meteor.Error('Experiences.methods.remove.denied', - 'You need to be logged in to remove an experience'); + 'You need to be logged in to remove an experience'); } let experience = Experiences.findOne(experienceId); if (!experience) return; let creatureId = experience.creatureId assertEditPermission(creatureId, userId); - if (experience.xp){ + if (experience.xp) { Creatures.update(creatureId, { $inc: { 'denormalizedStats.xp': -experience.xp }, $set: { dirty: true }, @@ -154,11 +154,11 @@ const recomputeExperiences = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({creatureId}) { + run({ creatureId }) { let userId = this.userId; if (!userId) { throw new Meteor.Error('Experiences.methods.recompute.denied', - 'You need to be logged in to recompute a creature\'s experiences'); + 'You need to be logged in to recompute a creature\'s experiences'); } assertEditPermission(creatureId, userId); @@ -167,16 +167,18 @@ const recomputeExperiences = new ValidatedMethod({ Experiences.find({ creatureId }, { - fields: {xp: 1, levels: 1} + fields: { xp: 1, levels: 1 } }).forEach(experience => { xp += experience.xp || 0; milestoneLevels += experience.levels || 0; }); - Creatures.update(creatureId, {$set: { - 'denormalizedStats.xp': xp, - 'denormalizedStats.milestoneLevels': milestoneLevels, - dirty: true, - }}); + Creatures.update(creatureId, { + $set: { + 'denormalizedStats.xp': xp, + 'denormalizedStats.milestoneLevels': milestoneLevels, + dirty: true, + } + }); }, }); diff --git a/app/imports/api/creature/journal/JournalEntry.js b/app/imports/api/creature/journal/JournalEntry.js index 43d5ecc2..5e65cb2b 100644 --- a/app/imports/api/creature/journal/JournalEntry.js +++ b/app/imports/api/creature/journal/JournalEntry.js @@ -5,18 +5,18 @@ let ExperienceSchema = new SimpleSchema({ title: { type: String, optional: true, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, // Potentially long description of the event description: { type: String, optional: true, - max: STORAGE_LIMITS.description, + max: STORAGE_LIMITS.description, }, // The real-world date that it occured date: { type: Date, - autoValue: function() { + autoValue: function () { // If the date isn't set, set it to now if (!this.isSet) { return new Date(); @@ -27,24 +27,24 @@ let ExperienceSchema = new SimpleSchema({ worldDate: { type: String, optional: true, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, - // Tags to better find this entry later - tags: { - type: Array, - defaultValue: [], - maxCount: STORAGE_LIMITS.tagCount, - }, - 'tags.$': { - type: String, - max: STORAGE_LIMITS.tagLength, - }, - // ID of the journal this entry belongs to - journalId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - } + // Tags to better find this entry later + tags: { + type: Array, + defaultValue: [], + maxCount: STORAGE_LIMITS.tagCount, + }, + 'tags.$': { + type: String, + max: STORAGE_LIMITS.tagLength, + }, + // ID of the journal this entry belongs to + journalId: { + type: String, + regEx: SimpleSchema.RegEx.Id, + index: 1, + } }); export { ExperienceSchema }; diff --git a/app/imports/api/creature/log/CreatureLogs.js b/app/imports/api/creature/log/CreatureLogs.js index de7777b7..5b858b29 100644 --- a/app/imports/api/creature/log/CreatureLogs.js +++ b/app/imports/api/creature/log/CreatureLogs.js @@ -4,13 +4,13 @@ import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables import LogContentSchema from '/imports/api/creature/log/LogContentSchema.js'; import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; -import {assertEditPermission} from '/imports/api/creature/creatures/creaturePermissions.js'; -import {parse, prettifyParseError} from '/imports/parser/parser.js'; +import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js'; +import { parse, prettifyParseError } from '/imports/parser/parser.js'; import resolve, { toString } from '/imports/parser/resolve.js'; const PER_CREATURE_LOG_LIMIT = 100; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; -if (Meteor.isServer){ +if (Meteor.isServer) { var sendWebhookAsCreature = require('/imports/server/discord/sendWebhook.js').sendWebhookAsCreature; } @@ -25,17 +25,17 @@ let CreatureLogSchema = new SimpleSchema({ 'content.$': { type: LogContentSchema, }, - // The real-world date that it occured, usually sorted by date - date: { - type: Date, - autoValue: function() { - // If the date isn't set, set it to now - if (!this.isSet) { - return new Date(); - } - }, + // The real-world date that it occured, usually sorted by date + date: { + type: Date, + autoValue: function () { + // If the date isn't set, set it to now + if (!this.isSet) { + return new Date(); + } + }, index: 1, - }, + }, creatureId: { type: String, regEx: SimpleSchema.RegEx.Id, @@ -50,23 +50,23 @@ let CreatureLogSchema = new SimpleSchema({ CreatureLogs.attachSchema(CreatureLogSchema); -function removeOldLogs(creatureId){ +function removeOldLogs(creatureId) { // Find the first log that is over the limit let firstExpiredLog = CreatureLogs.find({ creatureId }, { - sort: {date: -1}, + sort: { date: -1 }, skip: PER_CREATURE_LOG_LIMIT, }); if (!firstExpiredLog) return; // Remove all logs older than the one over the limit CreatureLogs.remove({ creatureId, - date: {$lte: firstExpiredLog.date}, + date: { $lte: firstExpiredLog.date }, }); } -function logToMessageData(log){ +function logToMessageData(log) { let embed = { fields: [], }; @@ -78,8 +78,8 @@ function logToMessageData(log){ return { embeds: [embed] }; } -function logWebhook({log, creature}){ - if (Meteor.isServer){ +function logWebhook({ log, creature }) { + if (Meteor.isServer) { sendWebhookAsCreature({ creature, data: logToMessageData(log), @@ -94,47 +94,49 @@ const insertCreatureLog = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - validate: new SimpleSchema({ - log: CreatureLogSchema.omit('date'), - }).validator(), - run({log}){ + validate: new SimpleSchema({ + log: CreatureLogSchema.omit('date'), + }).validator(), + run({ log }) { const creatureId = log.creatureId; - const creature = Creatures.findOne(creatureId, {fields: { - readers: 1, - writers: 1, - owner: 1, - 'settings.discordWebhook': 1, - name: 1, - avatarPicture: 1, - }}); + const creature = Creatures.findOne(creatureId, { + fields: { + readers: 1, + writers: 1, + owner: 1, + 'settings.discordWebhook': 1, + name: 1, + avatarPicture: 1, + } + }); assertEditPermission(creature, this.userId); // Build the new log - let id = insertCreatureLogWork({log, creature, method: this}) + let id = insertCreatureLogWork({ log, creature, method: this }) return id; }, }); -export function insertCreatureLogWork({log, creature, method}){ +export function insertCreatureLogWork({ log, creature, method }) { // Build the new log - if (typeof log === 'string'){ - log = {content: [{value: log}]}; + if (typeof log === 'string') { + log = { content: [{ value: log }] }; } if (!log.content?.length) return; log.date = new Date(); // Insert it let id = CreatureLogs.insert(log); - if (Meteor.isServer){ + if (Meteor.isServer) { method?.unblock(); removeOldLogs(creature._id); - logWebhook({log, creature}); + logWebhook({ log, creature }); } return id; } -function equalIgnoringWhitespace(a, b){ +function equalIgnoringWhitespace(a, b) { if (typeof a !== 'string' || typeof b !== 'string') return a === b; - return a.replace(/\s/g,'') === b.replace(/\s/g, ''); + return a.replace(/\s/g, '') === b.replace(/\s/g, ''); } const logRoll = new ValidatedMethod({ @@ -144,33 +146,35 @@ const logRoll = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - validate: new SimpleSchema({ - roll: { - type: String, - }, - creatureId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - }, - }).validator(), - run({roll, creatureId}){ - const creature = Creatures.findOne(creatureId, {fields: { - readers: 1, - writers: 1, - owner: 1, - 'settings.discordWebhook': 1, - name: 1, - avatarPicture: 1, - }}); + validate: new SimpleSchema({ + roll: { + type: String, + }, + creatureId: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + }).validator(), + run({ roll, creatureId }) { + const creature = Creatures.findOne(creatureId, { + fields: { + readers: 1, + writers: 1, + owner: 1, + 'settings.discordWebhook': 1, + name: 1, + avatarPicture: 1, + } + }); assertEditPermission(creature, this.userId); const variables = CreatureVariables.findOne({ _creatureId: creatureId }); let logContent = [] let parsedResult = undefined; try { parsedResult = parse(roll); - } catch (e){ + } catch (e) { let error = prettifyParseError(e); - logContent.push({name: 'Parse Error', value: error}); + logContent.push({ name: 'Parse Error', value: error }); } if (parsedResult) try { let { @@ -184,19 +188,19 @@ const logRoll = new ValidatedMethod({ logContent.push({ value: compiledString }); - let {result: rolled} = resolve('roll', compiled, variables, context); + let { result: rolled } = resolve('roll', compiled, variables, context); let rolledString = toString(rolled); if (rolledString !== compiledString) logContent.push({ value: rolledString }); - let {result} = resolve('reduce', rolled, variables, context); + let { result } = resolve('reduce', rolled, variables, context); let resultString = toString(result); if (resultString !== rolledString) logContent.push({ value: resultString }); - } catch (e){ + } catch (e) { console.error(e); - logContent = [{name: 'Calculation error'}]; + logContent = [{ name: 'Calculation error' }]; } const log = { content: logContent, @@ -204,11 +208,11 @@ const logRoll = new ValidatedMethod({ date: new Date(), }; - let id = insertCreatureLogWork({log, creature, method: this}); + let id = insertCreatureLogWork({ log, creature, method: this }); return id; }, }); export default CreatureLogs; -export { CreatureLogSchema, insertCreatureLog, logRoll, PER_CREATURE_LOG_LIMIT}; +export { CreatureLogSchema, insertCreatureLog, logRoll, PER_CREATURE_LOG_LIMIT }; diff --git a/app/imports/api/engine/actions/applyPropertyByType/applyBuff.js b/app/imports/api/engine/actions/applyPropertyByType/applyBuff.js index 93bf413c..4e68eabe 100644 --- a/app/imports/api/engine/actions/applyPropertyByType/applyBuff.js +++ b/app/imports/api/engine/actions/applyPropertyByType/applyBuff.js @@ -1,8 +1,8 @@ import { - setLineageOfDocs, - renewDocIds + setLineageOfDocs, + renewDocIds } from '/imports/api/parenting/parenting.js'; -import {setDocToLastOrder} from '/imports/api/parenting/order.js'; +import { setDocToLastOrder } from '/imports/api/parenting/order.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import computedSchemas from '/imports/api/properties/computedPropertySchemasIndex.js'; import applyFnToKey from '/imports/api/engine/computation/utility/applyFnToKey.js'; @@ -15,14 +15,14 @@ import cyrb53 from '/imports/api/engine/computation/utility/cyrb53.js'; import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js'; import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX.js'; -export default function applyBuff(node, actionContext){ +export default function applyBuff(node, actionContext) { applyNodeTriggers(node, 'before', actionContext); const prop = node.node; let buffTargets = prop.target === 'self' ? [actionContext.creature] : actionContext.targets; // Then copy the decendants of the buff to the targets let propList = [prop]; - function addChildrenToPropList(children, { skipCrystalize } = {}){ + function addChildrenToPropList(children, { skipCrystalize } = {}) { children.forEach(child => { if (skipCrystalize) child.node._skipCrystalize = true; propList.push(child.node); @@ -34,7 +34,7 @@ export default function applyBuff(node, actionContext){ } addChildrenToPropList(node.children); if (!prop.skipCrystalization) { - crystalizeVariables({propList, actionContext}); + crystalizeVariables({ propList, actionContext }); } let oldParent = { @@ -46,8 +46,8 @@ export default function applyBuff(node, actionContext){ copyNodeListToTarget(propList, target, oldParent); //Log the buff - if ((prop.name || prop.description?.value) && !prop.silent){ - if (target._id === actionContext.creature._id){ + if ((prop.name || prop.description?.value) && !prop.silent) { + if (target._id === actionContext.creature._id) { // Targeting self actionContext.addLog({ name: prop.name, @@ -72,8 +72,8 @@ export default function applyBuff(node, actionContext){ // Don't apply the children of the buff, they get copied to the target instead } -function copyNodeListToTarget(propList, target, oldParent){ - let ancestry = [{collection: 'creatures', id: target._id}]; +function copyNodeListToTarget(propList, target, oldParent) { + let ancestry = [{ collection: 'creatures', id: target._id }]; setLineageOfDocs({ docArray: propList, newAncestry: ancestry, @@ -93,14 +93,14 @@ function copyNodeListToTarget(propList, target, oldParent){ * Replaces all variables with their resolved values * except variables of the form `$target.thing.total` become `thing.total` */ -function crystalizeVariables({propList, actionContext}){ +function crystalizeVariables({ propList, actionContext }) { propList.forEach(prop => { if (prop._skipCrystalize) { delete prop._skipCrystalize; return; } // Iterate through all the calculations and crystalize them - computedSchemas[prop.type].computedFields().forEach( calcKey => { + computedSchemas[prop.type].computedFields().forEach(calcKey => { applyFnToKey(prop, calcKey, (prop, key) => { const calcObj = get(prop, key); if (!calcObj?.parseNode) return; @@ -110,12 +110,12 @@ function crystalizeVariables({propList, actionContext}){ node.parseType !== 'accessor' && node.parseType !== 'symbol' ) return node; // Handle variables - if (node.name === '$target'){ + if (node.name === '$target') { // strip $target - if (node.parseType === 'accessor'){ + if (node.parseType === 'accessor') { node.name = node.path.shift(); - if (!node.path.length){ - return symbol.create({name: node.name}) + if (!node.path.length) { + return symbol.create({ name: node.name }) } } else { // Can't strip symbols @@ -127,7 +127,7 @@ function crystalizeVariables({propList, actionContext}){ return node; } else { // Resolve all other variables - const {result, context} = resolve('reduce', node, actionContext.scope); + const { result, context } = resolve('reduce', node, actionContext.scope); logErrors(context.errors, actionContext); return result; } @@ -137,14 +137,14 @@ function crystalizeVariables({propList, actionContext}){ }); }); // For each key in the schema - computedSchemas[prop.type].inlineCalculationFields().forEach( calcKey => { + computedSchemas[prop.type].inlineCalculationFields().forEach(calcKey => { // That ends in .inlineCalculations applyFnToKey(prop, calcKey, (prop, key) => { const inlineCalcObj = get(prop, key); if (!inlineCalcObj) return; // If there is no text, skip - if (!inlineCalcObj.text){ + if (!inlineCalcObj.text) { return; } diff --git a/app/imports/api/engine/actions/doAction.js b/app/imports/api/engine/actions/doAction.js index 51934483..57c7beac 100644 --- a/app/imports/api/engine/actions/doAction.js +++ b/app/imports/api/engine/actions/doAction.js @@ -41,8 +41,8 @@ const doAction = new ValidatedMethod({ let action = CreatureProperties.findOne(actionId); const creatureId = action.ancestors[0].id; const actionContext = new ActionContext(creatureId, targetIds, this); - - // Check permissions + + // Check permissions assertEditPermission(actionContext.creature, this.userId); actionContext.targets.forEach(target => { assertEditPermission(target, this.userId); @@ -56,13 +56,13 @@ const doAction = new ValidatedMethod({ properties.sort((a, b) => a.order - b.order); // Do the action - doActionWork({properties, ancestors, actionContext, methodScope: scope}); + doActionWork({ properties, ancestors, actionContext, methodScope: scope }); // Recompute all involved creatures Creatures.update({ _id: { $in: [creatureId, ...targetIds] } }, { - $set: {dirty: true}, + $set: { dirty: true }, }); }, }); @@ -71,11 +71,11 @@ export default doAction; export function doActionWork({ properties, ancestors, actionContext, methodScope = {}, -}){ +}) { // get the docs const ancestorScope = getAncestorScope(ancestors); const propertyForest = nodeArrayToTree(properties); - if (propertyForest.length !== 1){ + if (propertyForest.length !== 1) { throw new Meteor.Error(`The action has ${propertyForest.length} top level properties, expected 1`); } @@ -91,7 +91,7 @@ export function doActionWork({ } // Assumes ancestors are in tree order already -function getAncestorScope(ancestors){ +function getAncestorScope(ancestors) { let scope = {}; ancestors.forEach(prop => { scope[`#${prop.type}`] = prop; diff --git a/app/imports/api/engine/actions/doCastSpell.js b/app/imports/api/engine/actions/doCastSpell.js index ef71759d..628e31d7 100644 --- a/app/imports/api/engine/actions/doCastSpell.js +++ b/app/imports/api/engine/actions/doCastSpell.js @@ -42,12 +42,12 @@ const doAction = new ValidatedMethod({ timeInterval: 5000, }, run({ spellId, slotId, targetIds = [], scope = {} }) { - // Get action context + // Get action context let spell = CreatureProperties.findOne(spellId); const creatureId = spell.ancestors[0].id; const actionContext = new ActionContext(creatureId, targetIds, this); - // Check permissions + // Check permissions assertEditPermission(actionContext.creature, this.userId); actionContext.targets.forEach(target => { assertEditPermission(target, this.userId); @@ -64,25 +64,25 @@ const doAction = new ValidatedMethod({ let slotLevel = spell.level || 0; let slot; - if (slotId && !spell.castWithoutSpellSlots){ + if (slotId && !spell.castWithoutSpellSlots) { slot = CreatureProperties.findOne(slotId); - if (!slot){ + if (!slot) { throw new Meteor.Error('No slot', 'Slot not found to cast spell'); } - if (!slot.value){ + if (!slot.value) { throw new Meteor.Error('No slot', 'Slot depleted'); } - if (slot.attributeType !== 'spellSlot'){ + if (slot.attributeType !== 'spellSlot') { throw new Meteor.Error('Not a slot', 'The given property is not a valid spell slot'); } - if (!slot.spellSlotLevel?.value){ + if (!slot.spellSlotLevel?.value) { throw new Meteor.Error('No slot level', 'Slot does not have a spell slot level'); } - if (slot.spellSlotLevel.value < spell.level){ + if (slot.spellSlotLevel.value < spell.level) { throw new Meteor.Error('Slot too small', 'Slot is not large enough to cast spell'); } @@ -96,7 +96,7 @@ const doAction = new ValidatedMethod({ } // Post the slot level spent to the log - if (slot?.spellSlotLevel?.value){ + if (slot?.spellSlotLevel?.value) { actionContext.addLog({ name: `Casting using a level ${slotLevel} spell slot` }); diff --git a/app/imports/api/engine/computation/computeComputation/computeByType/computeVariable/aggregate/aggregateEffect.js b/app/imports/api/engine/computation/computeComputation/computeByType/computeVariable/aggregate/aggregateEffect.js index 6cab306a..3b1b987e 100644 --- a/app/imports/api/engine/computation/computeComputation/computeByType/computeVariable/aggregate/aggregateEffect.js +++ b/app/imports/api/engine/computation/computeComputation/computeByType/computeVariable/aggregate/aggregateEffect.js @@ -1,4 +1,4 @@ -import { pick } from "lodash"; +import { pick } from 'lodash'; export default function aggregateEffect({node, linkedNode, link}){ if (link.data !== 'effect') return; diff --git a/app/imports/api/icons/Icons.js b/app/imports/api/icons/Icons.js index 286a4bee..072d2467 100644 --- a/app/imports/api/icons/Icons.js +++ b/app/imports/api/icons/Icons.js @@ -7,17 +7,17 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; let Icons = new Mongo.Collection('icons'); let iconsSchema = new SimpleSchema({ - name: { - type: String, + name: { + type: String, unique: true, max: STORAGE_LIMITS.name, index: 1, - }, - description: { - type: String, - optional: true, + }, + description: { + type: String, + optional: true, max: STORAGE_LIMITS.description, - }, + }, tags: { type: Array, optional: true, @@ -38,7 +38,7 @@ if (Meteor.isServer) { Icons._ensureIndex({ 'name': 'text', 'description': 'text', - 'tags': 'text', + 'tags': 'text', }); } @@ -55,15 +55,15 @@ Icons.attachSchema(iconsSchema); // This method does not validate icons against the schema, use wisely; const writeIcons = new ValidatedMethod({ - name: 'icons.write', - validate: null, - run(icons){ + name: 'icons.write', + validate: null, + run(icons) { assertAdmin(this.userId); - if (Meteor.isServer){ + if (Meteor.isServer) { this.unblock(); - Icons.rawCollection().insert(icons, {ordered: false}); + Icons.rawCollection().insert(icons, { ordered: false }); } - } + } }); const findIcons = new ValidatedMethod({ @@ -80,11 +80,11 @@ const findIcons = new ValidatedMethod({ numRequests: 20, timeInterval: 10000, }, - run({search}){ + run({ search }) { if (!search) return []; if (!Meteor.isServer) return; return Icons.find( - { $text: {$search: search} }, + { $text: { $search: search } }, { // relevant documents have a higher score. fields: { diff --git a/app/imports/api/library/Libraries.js b/app/imports/api/library/Libraries.js index 95444bc3..1e46c672 100644 --- a/app/imports/api/library/Libraries.js +++ b/app/imports/api/library/Libraries.js @@ -21,14 +21,14 @@ let Libraries = new Mongo.Collection('libraries'); let LibrarySchema = new SimpleSchema({ name: { - type: String, - max: STORAGE_LIMITS.name, - }, - description: { - type: String, - optional: true, - max: STORAGE_LIMITS.summary, - }, + type: String, + max: STORAGE_LIMITS.name, + }, + description: { + type: String, + optional: true, + max: STORAGE_LIMITS.summary, + }, }); LibrarySchema.extend(SharingSchema); @@ -38,24 +38,24 @@ Libraries.attachSchema(LibrarySchema); export default Libraries; const insertLibrary = new ValidatedMethod({ - name: 'libraries.insert', + name: 'libraries.insert', mixins: [ simpleSchemaMixin, - ], - schema: LibrarySchema.omit('owner'), - run(library) { - if (!this.userId) { - throw new Meteor.Error('Libraries.methods.insert.denied', - 'You need to be logged in to insert a library'); - } - let tier = getUserTier(this.userId); - if (!tier.paidBenefits){ - throw new Meteor.Error('Libraries.methods.insert.denied', - `The ${tier.name} tier does not allow you to insert a library`); - } - library.owner = this.userId; + ], + schema: LibrarySchema.omit('owner'), + run(library) { + if (!this.userId) { + throw new Meteor.Error('Libraries.methods.insert.denied', + 'You need to be logged in to insert a library'); + } + let tier = getUserTier(this.userId); + if (!tier.paidBenefits) { + throw new Meteor.Error('Libraries.methods.insert.denied', + `The ${tier.name} tier does not allow you to insert a library`); + } + library.owner = this.userId; return Libraries.insert(library); - }, + }, }); const updateLibraryName = new ValidatedMethod({ @@ -69,15 +69,15 @@ const updateLibraryName = new ValidatedMethod({ type: String, }, }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({_id, name}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ _id, name }) { let library = Libraries.findOne(_id); assertEditPermission(library, this.userId); - Libraries.update(_id, {$set: {name}}); + Libraries.update(_id, { $set: { name } }); }, }); @@ -92,15 +92,15 @@ const updateLibraryDescription = new ValidatedMethod({ type: String, }, }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({_id, description}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ _id, description }) { let library = Libraries.findOne(_id); assertEditPermission(library, this.userId); - Libraries.update(_id, {$set: {description}}); + Libraries.update(_id, { $set: { description } }); }, }); @@ -112,22 +112,22 @@ const removeLibrary = new ValidatedMethod({ regEx: SimpleSchema.RegEx.id }, }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({_id}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ _id }) { let library = Libraries.findOne(_id); assertOwnership(library, this.userId); - this.unblock(); - removeLibaryWork(_id) + this.unblock(); + removeLibaryWork(_id) } }); -export function removeLibaryWork(libraryId){ - Libraries.remove(libraryId); - LibraryNodes.remove({'ancestors.id': libraryId}); +export function removeLibaryWork(libraryId) { + Libraries.remove(libraryId); + LibraryNodes.remove({ 'ancestors.id': libraryId }); } export { LibrarySchema, insertLibrary, updateLibraryName, updateLibraryDescription, removeLibrary }; diff --git a/app/imports/api/library/LibraryNodes.js b/app/imports/api/library/LibraryNodes.js index 283a8a68..50d97cd3 100644 --- a/app/imports/api/library/LibraryNodes.js +++ b/app/imports/api/library/LibraryNodes.js @@ -23,28 +23,28 @@ let LibraryNodeSchema = new SimpleSchema({ type: String, regEx: SimpleSchema.RegEx.Id, }, - type: { + type: { type: String, allowedValues: Object.keys(propertySchemasIndex), }, - tags: { - type: Array, - defaultValue: [], + tags: { + type: Array, + defaultValue: [], maxCount: STORAGE_LIMITS.tagCount, - }, - 'tags.$': { - type: String, + }, + 'tags.$': { + type: String, max: STORAGE_LIMITS.tagLength, - }, + }, libraryTags: { - type: Array, - defaultValue: [], + type: Array, + defaultValue: [], maxCount: STORAGE_LIMITS.tagCount, - }, - 'libraryTags.$': { - type: String, + }, + 'libraryTags.$': { + type: String, max: STORAGE_LIMITS.tagLength, - }, + }, icon: { type: storedIconsSchema, optional: true, @@ -56,37 +56,37 @@ let LibraryNodeSchema = new SimpleSchema({ if (Meteor.isServer) { LibraryNodes._ensureIndex({ 'name': 'text', - 'tags': 'text', + 'tags': 'text', }); } -for (let key in propertySchemasIndex){ - let schema = new SimpleSchema({}); - schema.extend(LibraryNodeSchema); +for (let key in propertySchemasIndex) { + let schema = new SimpleSchema({}); + schema.extend(LibraryNodeSchema); schema.extend(ColorSchema); - schema.extend(propertySchemasIndex[key]); - schema.extend(ChildSchema); - schema.extend(SoftRemovableSchema); - LibraryNodes.attachSchema(schema, { - selector: {type: key} - }); + schema.extend(propertySchemasIndex[key]); + schema.extend(ChildSchema); + schema.extend(SoftRemovableSchema); + LibraryNodes.attachSchema(schema, { + selector: { type: key } + }); } -function getLibrary(node){ +function getLibrary(node) { if (!node) throw new Meteor.Error('No node provided'); let library = Libraries.findOne(node.ancestors[0].id); if (!library) throw new Meteor.Error('Library does not exist'); return library; } -function assertNodeEditPermission(node, userId){ +function assertNodeEditPermission(node, userId) { let lib = getLibrary(node); return assertEditPermission(lib, userId); } const insertNode = new ValidatedMethod({ name: 'libraryNodes.insert', - validate: null, + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, @@ -95,8 +95,8 @@ const insertNode = new ValidatedMethod({ run(libraryNode) { delete libraryNode._id; assertNodeEditPermission(libraryNode, this.userId); - let nodeId = LibraryNodes.insert(libraryNode); - if (libraryNode.type == 'reference'){ + let nodeId = LibraryNodes.insert(libraryNode); + if (libraryNode.type == 'reference') { libraryNode._id = nodeId; updateReferenceNodeWork(libraryNode, this.userId); } @@ -106,37 +106,37 @@ const insertNode = new ValidatedMethod({ const updateLibraryNode = new ValidatedMethod({ name: 'libraryNodes.update', - validate({_id, path}){ - if (!_id) return false; - // We cannot change these fields with a simple update - switch (path[0]){ - case 'type': + validate({ _id, path }) { + if (!_id) return false; + // We cannot change these fields with a simple update + switch (path[0]) { + case 'type': case 'order': case 'parent': case 'ancestors': - return false; - } + return false; + } }, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id, path, value}) { + run({ _id, path, value }) { let node = LibraryNodes.findOne(_id); assertNodeEditPermission(node, this.userId); let pathString = path.join('.'); let modifier; // unset empty values - if (value === null || value === undefined){ - modifier = {$unset: {[pathString]: 1}}; + if (value === null || value === undefined) { + modifier = { $unset: { [pathString]: 1 } }; } else { - modifier = {$set: {[pathString]: value}}; + modifier = { $set: { [pathString]: value } }; } - let numUpdated = LibraryNodes.update(_id, modifier, { - selector: {type: node.type}, - }); - if (node.type == 'reference'){ + let numUpdated = LibraryNodes.update(_id, modifier, { + selector: { type: node.type }, + }); + if (node.type == 'reference') { node = LibraryNodes.findOne(_id); updateReferenceNodeWork(node, this.userId); } @@ -145,87 +145,87 @@ const updateLibraryNode = new ValidatedMethod({ }); const pushToLibraryNode = new ValidatedMethod({ - name: 'libraryNodes.push', - validate: null, + name: 'libraryNodes.push', + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id, path, value}){ - let node = LibraryNodes.findOne(_id); + run({ _id, path, value }) { + let node = LibraryNodes.findOne(_id); assertNodeEditPermission(node, this.userId); - return LibraryNodes.update(_id, { - $push: {[path.join('.')]: value}, - }, { - selector: {type: node.type}, - }); - } + return LibraryNodes.update(_id, { + $push: { [path.join('.')]: value }, + }, { + selector: { type: node.type }, + }); + } }); const pullFromLibraryNode = new ValidatedMethod({ - name: 'libraryNodes.pull', - validate: null, + name: 'libraryNodes.pull', + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id, path, itemId}){ - let node = LibraryNodes.findOne(_id); + run({ _id, path, itemId }) { + let node = LibraryNodes.findOne(_id); assertNodeEditPermission(node, this.userId); - return LibraryNodes.update(_id, { - $pull: {[path.join('.')]: {_id: itemId}}, - }, { - selector: {type: node.type}, - getAutoValues: false, - }); - } + return LibraryNodes.update(_id, { + $pull: { [path.join('.')]: { _id: itemId } }, + }, { + selector: { type: node.type }, + getAutoValues: false, + }); + } }); const softRemoveLibraryNode = new ValidatedMethod({ - name: 'libraryNodes.softRemove', - validate: new SimpleSchema({ - _id: SimpleSchema.RegEx.Id - }).validator(), + name: 'libraryNodes.softRemove', + validate: new SimpleSchema({ + _id: SimpleSchema.RegEx.Id + }).validator(), mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id}){ - let node = LibraryNodes.findOne(_id); + run({ _id }) { + let node = LibraryNodes.findOne(_id); assertNodeEditPermission(node, this.userId); - softRemove({_id, collection: LibraryNodes}); - } + softRemove({ _id, collection: LibraryNodes }); + } }); const restoreLibraryNode = new ValidatedMethod({ - name: 'libraryNodes.restore', - validate: new SimpleSchema({ - _id: SimpleSchema.RegEx.Id - }).validator(), + name: 'libraryNodes.restore', + validate: new SimpleSchema({ + _id: SimpleSchema.RegEx.Id + }).validator(), mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, - run({_id}){ + run({ _id }) { // Permissions let node = LibraryNodes.findOne(_id); assertNodeEditPermission(node, this.userId); // Do work - restore({_id, collection: LibraryNodes}); - } + restore({ _id, collection: LibraryNodes }); + } }); export default LibraryNodes; export { - LibraryNodeSchema, - insertNode, - updateLibraryNode, - pullFromLibraryNode, - pushToLibraryNode, - softRemoveLibraryNode, + LibraryNodeSchema, + insertNode, + updateLibraryNode, + pullFromLibraryNode, + pushToLibraryNode, + softRemoveLibraryNode, restoreLibraryNode, }; diff --git a/app/imports/api/library/methods/duplicateLibraryNode.js b/app/imports/api/library/methods/duplicateLibraryNode.js index 4da84997..107f3c6b 100644 --- a/app/imports/api/library/methods/duplicateLibraryNode.js +++ b/app/imports/api/library/methods/duplicateLibraryNode.js @@ -4,13 +4,13 @@ import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import { assertDocEditPermission } from '/imports/api/sharing/sharingPermissions.js'; import { - setLineageOfDocs, - renewDocIds + setLineageOfDocs, + renewDocIds } from '/imports/api/parenting/parenting.js'; import { reorderDocs } from '/imports/api/parenting/order.js'; var snackbar; -if (Meteor.isClient){ +if (Meteor.isClient) { snackbar = require( '/imports/ui/components/snackbars/SnackbarQueue.js' ).snackbar @@ -20,7 +20,7 @@ const DUPLICATE_CHILDREN_LIMIT = 50; const duplicateLibraryNode = new ValidatedMethod({ name: 'libraryNodes.duplicate', - validate: new SimpleSchema({ + validate: new SimpleSchema({ _id: { type: String, regEx: SimpleSchema.RegEx.Id, @@ -31,7 +31,7 @@ const duplicateLibraryNode = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({_id}) { + run({ _id }) { let libraryNode = LibraryNodes.findOne(_id); assertDocEditPermission(libraryNode, this.userId); @@ -40,16 +40,16 @@ const duplicateLibraryNode = new ValidatedMethod({ libraryNode._id = libraryNodeId; let nodes = LibraryNodes.find({ - 'ancestors.id': _id, - removed: {$ne: true}, - }, { + 'ancestors.id': _id, + removed: { $ne: true }, + }, { limit: DUPLICATE_CHILDREN_LIMIT + 1, - sort: {order: 1}, + sort: { order: 1 }, }).fetch(); - if (nodes.length > DUPLICATE_CHILDREN_LIMIT){ + if (nodes.length > DUPLICATE_CHILDREN_LIMIT) { nodes.pop(); - if (Meteor.isClient){ + if (Meteor.isClient) { snackbar({ text: `Only the first ${DUPLICATE_CHILDREN_LIMIT} children were duplicated`, }); @@ -58,21 +58,21 @@ const duplicateLibraryNode = new ValidatedMethod({ // re-map all the ancestors setLineageOfDocs({ - docArray: nodes, - newAncestry : [ + docArray: nodes, + newAncestry: [ ...libraryNode.ancestors, - {id: libraryNodeId, collection: 'libraryNodes'} + { id: libraryNodeId, collection: 'libraryNodes' } ], - oldParent : {id: _id, collection: 'libraryNodes'}, - }); + oldParent: { id: _id, collection: 'libraryNodes' }, + }); // Give the docs new IDs without breaking internal references - renewDocIds({docArray: nodes}); + renewDocIds({ docArray: nodes }); // Order the root node libraryNode.order += 0.5; - LibraryNodes.batchInsert([libraryNode, ...nodes]); + LibraryNodes.batchInsert([libraryNode, ...nodes]); // Tree structure changed by inserts, reorder the tree reorderDocs({ diff --git a/app/imports/api/parenting/ChildSchema.js b/app/imports/api/parenting/ChildSchema.js index c2a6bc69..f4787bcc 100644 --- a/app/imports/api/parenting/ChildSchema.js +++ b/app/imports/api/parenting/ChildSchema.js @@ -22,7 +22,7 @@ let ChildSchema = new SimpleSchema({ order: { type: Number, }, - parent: { + parent: { type: RefSchema, optional: true, }, diff --git a/app/imports/api/parenting/SoftRemovableSchema.js b/app/imports/api/parenting/SoftRemovableSchema.js index 8c120553..54c2f92c 100644 --- a/app/imports/api/parenting/SoftRemovableSchema.js +++ b/app/imports/api/parenting/SoftRemovableSchema.js @@ -1,17 +1,17 @@ import SimpleSchema from 'simpl-schema'; let SoftRemovableSchema = new SimpleSchema({ - "removed": { + 'removed': { type: Boolean, optional: true, index: 1, }, - "removedAt": { + 'removedAt': { type: Date, optional: true, index: 1, }, - "removedWith": { + 'removedWith': { optional: true, type: String, regEx: SimpleSchema.RegEx.Id, diff --git a/app/imports/api/properties/Adjustments.js b/app/imports/api/properties/Adjustments.js index 0d1edb6a..6b2607f5 100644 --- a/app/imports/api/properties/Adjustments.js +++ b/app/imports/api/properties/Adjustments.js @@ -3,7 +3,7 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; const AdjustmentSchema = createPropertySchema({ - // The roll that determines how much to change the attribute + // The roll that determines how much to change the attribute // This can be simplified, but should only compute when activated amount: { type: 'fieldToCompute', @@ -11,21 +11,21 @@ const AdjustmentSchema = createPropertySchema({ optional: true, defaultValue: 1, }, - // Who this adjustment applies to - target: { - type: String, + // Who this adjustment applies to + target: { + type: String, defaultValue: 'target', - allowedValues: [ + allowedValues: [ 'self', 'target', ], - }, - // The stat this rolls applies to - stat: { - type: String, + }, + // The stat this rolls applies to + stat: { + type: String, optional: true, max: STORAGE_LIMITS.variableName, - }, + }, operation: { type: String, allowedValues: ['set', 'increment'], diff --git a/app/imports/api/properties/Attributes.js b/app/imports/api/properties/Attributes.js index 51174362..d486d5f9 100644 --- a/app/imports/api/properties/Attributes.js +++ b/app/imports/api/properties/Attributes.js @@ -8,34 +8,34 @@ import createPropertySchema from '/imports/api/properties/subSchemas/createPrope */ let AttributeSchema = createPropertySchema({ name: { - type: String, + type: String, optional: true, max: STORAGE_LIMITS.name, - }, + }, // The technical, lowercase, single-word name used in formulae variableName: { type: String, optional: true, - regEx: VARIABLE_NAME_REGEX, + regEx: VARIABLE_NAME_REGEX, min: 2, max: STORAGE_LIMITS.variableName, }, - // How it is displayed and computed is determined by type + // How it is displayed and computed is determined by type attributeType: { type: String, allowedValues: [ 'ability', //Strength, Dex, Con, etc. 'stat', // Speed, Armor Class - 'modifier', // Proficiency Bonus, displayed as +x + 'modifier', // Proficiency Bonus, displayed as +x 'hitDice', // d12 hit dice 'healthBar', // Hitpoints, Temporary Hitpoints, can take damage - 'bar', // Displayed as a health bar, can't take damage + 'bar', // Displayed as a health bar, can't take damage 'resource', // Rages, sorcery points 'spellSlot', // Level 1, 2, 3... spell slots 'utility', // Aren't displayed, Jump height, Carry capacity ], defaultValue: 'stat', - index: 1, + index: 1, }, // For type hitDice, the size needs to be stored separately hitDiceSize: { @@ -46,19 +46,19 @@ let AttributeSchema = createPropertySchema({ // For type spellSlot, the level needs to be stored separately spellSlotLevel: { type: 'fieldToCompute', - optional: true, + optional: true, }, // For type healthBar midColor, and lowColor can be set separately from the // property's color, which is used as the undamaged color 'healthBarColorMid': { - type: String, - regEx: /^#([a-f0-9]{3}){1,2}\b$/i, - optional: true, + type: String, + regEx: /^#([a-f0-9]{3}){1,2}\b$/i, + optional: true, }, 'healthBarColorLow': { - type: String, - regEx: /^#([a-f0-9]{3}){1,2}\b$/i, - optional: true, + type: String, + regEx: /^#([a-f0-9]{3}){1,2}\b$/i, + optional: true, }, // Control how the health bar takes damage or healing healthBarNoDamage: { @@ -68,7 +68,7 @@ let AttributeSchema = createPropertySchema({ healthBarNoHealing: { type: Boolean, optional: true, - }, + }, healthBarDamageOrder: { type: SimpleSchema.Integer, optional: true, @@ -77,17 +77,17 @@ let AttributeSchema = createPropertySchema({ type: SimpleSchema.Integer, optional: true, }, - // The starting value, before effects - baseValue: { + // The starting value, before effects + baseValue: { type: 'fieldToCompute', - optional: true, - }, + optional: true, + }, // Description of what the attribute is used for description: { type: 'inlineCalculationFieldToCompute', - optional: true, - }, - // The damage done to the attribute, should always compute as positive + optional: true, + }, + // The damage done to the attribute, should always compute as positive damage: { type: SimpleSchema.Integer, optional: true, @@ -107,7 +107,7 @@ let AttributeSchema = createPropertySchema({ type: Boolean, optional: true, }, - // Automatically zero the adjustment on these conditions + // Automatically zero the adjustment on these conditions reset: { type: String, optional: true, @@ -126,9 +126,9 @@ let ComputedOnlyAttributeSchema = createPropertySchema({ }, spellSlotLevel: { type: 'computedOnlyField', - optional: true, + optional: true, }, - // The computed value of the attribute + // The computed value of the attribute total: { type: SimpleSchema.oneOf(Number, String, Boolean), optional: true, @@ -137,27 +137,27 @@ let ComputedOnlyAttributeSchema = createPropertySchema({ // The computed value of the attribute minus the damage value: { type: SimpleSchema.oneOf(Number, String, Boolean), - defaultValue: 0, + defaultValue: 0, optional: true, removeBeforeCompute: true, }, - // The computed modifier, provided the attribute type is `ability` - modifier: { - type: SimpleSchema.Integer, - optional: true, + // The computed modifier, provided the attribute type is `ability` + modifier: { + type: SimpleSchema.Integer, + optional: true, removeBeforeCompute: true, - }, + }, // Attributes with proficiency grant it to all skills based on the attribute proficiency: { - type: Number, + type: Number, allowedValues: [0, 0.49, 0.5, 1, 2], - optional: true, + optional: true, removeBeforeCompute: true, - }, + }, // The computed creature constitution modifier for hit dice constitutionMod: { type: Number, - optional: true, + optional: true, removeBeforeCompute: true, }, // Should this attribute hide diff --git a/app/imports/api/properties/Branches.js b/app/imports/api/properties/Branches.js index 386773a1..73716eb6 100644 --- a/app/imports/api/properties/Branches.js +++ b/app/imports/api/properties/Branches.js @@ -3,8 +3,8 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; let BranchSchema = createPropertySchema({ - branchType: { - type: String, + branchType: { + type: String, allowedValues: [ // Uses the condition field to determine whether to apply children 'if', @@ -26,7 +26,7 @@ let BranchSchema = createPropertySchema({ //'option', ], defaultValue: 'if', - }, + }, text: { type: String, optional: true, diff --git a/app/imports/api/properties/BuffRemovers.js b/app/imports/api/properties/BuffRemovers.js index ae86bf5e..b96466cb 100644 --- a/app/imports/api/properties/BuffRemovers.js +++ b/app/imports/api/properties/BuffRemovers.js @@ -4,31 +4,31 @@ import createPropertySchema from '/imports/api/properties/subSchemas/createPrope let BuffRemoverSchema = createPropertySchema({ name: { - type: String, - optional: true, + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, - // This will remove just the nearest ancestor buff - targetParentBuff: { - type: Boolean, - optional: true, - }, - // The following only applies when not targeting the parent buff - // Which character to remove buffs from - target: { - type: String, - allowedValues: [ + }, + // This will remove just the nearest ancestor buff + targetParentBuff: { + type: Boolean, + optional: true, + }, + // The following only applies when not targeting the parent buff + // Which character to remove buffs from + target: { + type: String, + allowedValues: [ 'self', 'target', ], - defaultValue: 'target', - }, - // remove 1 or remove all - removeAll: { - type: Boolean, + defaultValue: 'target', + }, + // remove 1 or remove all + removeAll: { + type: Boolean, optional: true, defaultValue: true, - }, + }, // Buffs to remove based on tags: targetTags: { type: Array, @@ -50,7 +50,7 @@ let BuffRemoverSchema = createPropertySchema({ 'extraTags.$._id': { type: String, regEx: SimpleSchema.RegEx.Id, - autoValue(){ + autoValue() { if (!this.isSet) return Random.id(); } }, diff --git a/app/imports/api/properties/Buffs.js b/app/imports/api/properties/Buffs.js index 2e15d441..86584694 100644 --- a/app/imports/api/properties/Buffs.js +++ b/app/imports/api/properties/Buffs.js @@ -3,10 +3,10 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; let BuffSchema = createPropertySchema({ - name: { + name: { type: String, optional: true, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, description: { type: 'inlineCalculationFieldToCompute', @@ -16,36 +16,36 @@ let BuffSchema = createPropertySchema({ type: Boolean, optional: true, }, - // How many rounds this buff lasts + // How many rounds this buff lasts duration: { type: 'fieldToCompute', optional: true, }, - target: { + target: { type: String, allowedValues: [ - 'self', - 'target', - ], + 'self', + 'target', + ], defaultValue: 'target', }, // Prevent the property from showing up in the log - silent: { - type: Boolean, - optional: true, + silent: { + type: Boolean, + optional: true, }, // Prevent the children from being crystalized - skipCrystalization: { - type: Boolean, - optional: true, - }, + skipCrystalization: { + type: Boolean, + optional: true, + }, }); let ComputedOnlyBuffSchema = createPropertySchema({ description: { type: 'computedOnlyInlineCalculationField', optional: true, - max: STORAGE_LIMITS.description, + max: STORAGE_LIMITS.description, }, duration: { type: 'computedOnlyField', @@ -58,11 +58,11 @@ let ComputedOnlyBuffSchema = createPropertySchema({ }, appliedBy: { type: Object, - optional: true, + optional: true, }, 'appliedBy.name': { type: String, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, 'appliedBy.id': { type: String, @@ -70,12 +70,12 @@ let ComputedOnlyBuffSchema = createPropertySchema({ }, 'appliedBy.collection': { type: String, - max: STORAGE_LIMITS.collectionName, + max: STORAGE_LIMITS.collectionName, }, }); const ComputedBuffSchema = new SimpleSchema() - .extend(BuffSchema) - .extend(ComputedOnlyBuffSchema); + .extend(BuffSchema) + .extend(ComputedOnlyBuffSchema); export { BuffSchema, ComputedOnlyBuffSchema, ComputedBuffSchema }; diff --git a/app/imports/api/properties/ClassLevels.js b/app/imports/api/properties/ClassLevels.js index f0600917..bbd76d58 100644 --- a/app/imports/api/properties/ClassLevels.js +++ b/app/imports/api/properties/ClassLevels.js @@ -4,26 +4,26 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; const ClassLevelSchema = createPropertySchema({ - name: { - type: String, - optional: true, + name: { + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, - description: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, - // The name of this class level's variable - variableName: { + }, + description: { + type: 'inlineCalculationFieldToCompute', + optional: true, + }, + // The name of this class level's variable + variableName: { type: String, min: 2, - regEx: VARIABLE_NAME_REGEX, + regEx: VARIABLE_NAME_REGEX, max: STORAGE_LIMITS.variableName, optional: true, }, - level: { + level: { type: SimpleSchema.Integer, - defaultValue: 1, + defaultValue: 1, max: STORAGE_LIMITS.levelMax, }, // Filters out of UI if condition isn't met, but isn't otherwise enforced @@ -34,7 +34,7 @@ const ClassLevelSchema = createPropertySchema({ }, }); -const ComputedOnlyClassLevelSchema = createPropertySchema({ +const ComputedOnlyClassLevelSchema = createPropertySchema({ description: { type: 'computedOnlyInlineCalculationField', optional: true, diff --git a/app/imports/api/properties/Constants.js b/app/imports/api/properties/Constants.js index 0995ccd9..ded0f090 100644 --- a/app/imports/api/properties/Constants.js +++ b/app/imports/api/properties/Constants.js @@ -13,29 +13,29 @@ import resolve, { Context, traverse } from '/imports/parser/resolve.js'; */ let ConstantSchema = new SimpleSchema({ name: { - type: String, - optional: true, + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, + }, // The technical, lowercase, single-word name used in formulae variableName: { type: String, - regEx: VARIABLE_NAME_REGEX, + regEx: VARIABLE_NAME_REGEX, min: 2, defaultValue: 'newConstant', max: STORAGE_LIMITS.variableName, }, - // The input value to be parsed, must return a constant node or an array + // The input value to be parsed, must return a constant node or an array // of constant nodes to be valid - calculation: { - type: String, - optional: true, + calculation: { + type: String, + optional: true, max: STORAGE_LIMITS.calculation, - }, + }, errors: { type: Array, maxCount: STORAGE_LIMITS.errorCount, - autoValue(){ + autoValue() { let calc = this.field('calculation'); if (!calc.isSet && this.isModifier) { this.unset() @@ -44,27 +44,27 @@ let ConstantSchema = new SimpleSchema({ let string = calc.value; if (!string) return []; // Evaluate the calculation with no scope - let {result, context} = parseString(string); + let { result, context } = parseString(string); // Any existing errors will result in an early failure if (context && context.errors.length) return context.errors; // Ban variables in constants if necessary result && traverse(result, node => { - if (node.parseType === 'symbol' || node.parseType === 'accessor'){ + if (node.parseType === 'symbol' || node.parseType === 'accessor') { context.error('Variables can\'t be used to define a constant'); } }); return context && context.errors || []; } }, - 'errors.$':{ + 'errors.$': { type: ErrorSchema, }, }); -function parseString(string, fn = 'compile'){ +function parseString(string, fn = 'compile') { let context = new Context(); - if (!string){ - return {result: string, context}; + if (!string) { + return { result: string, context }; } // Parse the string using mathjs @@ -74,11 +74,11 @@ function parseString(string, fn = 'compile'){ } catch (e) { let message = prettifyParseError(e); context.error(message); - return {context}; + return { context }; } - if (!node) return {context}; - let {result} = resolve(fn, node, {/*empty scope*/}, context); - return {result, context} + if (!node) return { context }; + let { result } = resolve(fn, node, {/*empty scope*/ }, context); + return { result, context } } const ComputedOnlyConstantSchema = new SimpleSchema({}); diff --git a/app/imports/api/properties/Containers.js b/app/imports/api/properties/Containers.js index 402a3e83..565e0be6 100644 --- a/app/imports/api/properties/Containers.js +++ b/app/imports/api/properties/Containers.js @@ -7,7 +7,7 @@ let ContainerSchema = createPropertySchema({ type: String, optional: true, trim: false, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, carried: { type: Boolean, @@ -21,12 +21,12 @@ let ContainerSchema = createPropertySchema({ weight: { type: Number, min: 0, - optional: true, + optional: true, }, value: { type: Number, min: 0, - optional: true, + optional: true, }, description: { type: 'inlineCalculationFieldToCompute', @@ -35,33 +35,33 @@ let ContainerSchema = createPropertySchema({ }); const ComputedOnlyContainerSchema = createPropertySchema({ - description: { + description: { type: 'computedOnlyInlineCalculationField', optional: true, }, - // Weight of all the contents, zero if `contentsWeightless` is true - contentsWeight:{ - type: Number, - optional: true, - removeBeforeCompute: true, - }, - // Weight of all the carried contents (some sub-containers might not be carried) - // zero if `contentsWeightless` is true - carriedWeight:{ - type: Number, - optional: true, - removeBeforeCompute: true, - }, - contentsValue:{ - type: Number, - optional: true, - removeBeforeCompute: true, - }, - carriedValue:{ - type: Number, - optional: true, - removeBeforeCompute: true, - }, + // Weight of all the contents, zero if `contentsWeightless` is true + contentsWeight: { + type: Number, + optional: true, + removeBeforeCompute: true, + }, + // Weight of all the carried contents (some sub-containers might not be carried) + // zero if `contentsWeightless` is true + carriedWeight: { + type: Number, + optional: true, + removeBeforeCompute: true, + }, + contentsValue: { + type: Number, + optional: true, + removeBeforeCompute: true, + }, + carriedValue: { + type: Number, + optional: true, + removeBeforeCompute: true, + }, }); const ComputedContainerSchema = new SimpleSchema() diff --git a/app/imports/api/properties/DamageMultipliers.js b/app/imports/api/properties/DamageMultipliers.js index c88c4cbe..3c75fbbf 100644 --- a/app/imports/api/properties/DamageMultipliers.js +++ b/app/imports/api/properties/DamageMultipliers.js @@ -8,10 +8,10 @@ import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js'; */ let DamageMultiplierSchema = new SimpleSchema({ name: { - type: String, - optional: true, + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, + }, damageTypes: { type: Array, defaultValue: [], @@ -23,11 +23,11 @@ let DamageMultiplierSchema = new SimpleSchema({ max: STORAGE_LIMITS.calculation, regEx: VARIABLE_NAME_REGEX, }, - // The value of the damage multiplier - value: { + // The value of the damage multiplier + value: { type: Number, - defaultValue: 0.5, - allowedValues: [0, 0.5, 2], + defaultValue: 0.5, + allowedValues: [0, 0.5, 2], }, // Tags which bypass this multiplier (OR) excludeTags: { diff --git a/app/imports/api/properties/Damages.js b/app/imports/api/properties/Damages.js index 8f5e2a67..190dd4b5 100644 --- a/app/imports/api/properties/Damages.js +++ b/app/imports/api/properties/Damages.js @@ -4,7 +4,7 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js'; const DamageSchema = createPropertySchema({ - // The roll that determines how much to damage the attribute + // The roll that determines how much to damage the attribute // This can be simplified, but only computed when applied amount: { type: 'fieldToCompute', @@ -12,19 +12,19 @@ const DamageSchema = createPropertySchema({ defaultValue: '1d8 + strength.modifier', parseLevel: 'compile', }, - // Who this damage applies to - target: { - type: String, + // Who this damage applies to + target: { + type: String, defaultValue: 'target', - allowedValues: [ + allowedValues: [ 'self', 'target', ], - }, - damageType: { - type: String, + }, + damageType: { + type: String, max: STORAGE_LIMITS.calculation, - defaultValue: 'slashing', + defaultValue: 'slashing', regEx: VARIABLE_NAME_REGEX, }, // Prevent the property from showing up in the log diff --git a/app/imports/api/properties/Features.js b/app/imports/api/properties/Features.js index 0abe8be9..91fc95b6 100644 --- a/app/imports/api/properties/Features.js +++ b/app/imports/api/properties/Features.js @@ -3,19 +3,19 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; let FeatureSchema = createPropertySchema({ - name: { - type: String, + name: { + type: String, max: STORAGE_LIMITS.name, optional: true, - }, - summary: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, + }, + summary: { + type: 'inlineCalculationFieldToCompute', + optional: true, + }, description: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, + type: 'inlineCalculationFieldToCompute', + optional: true, + }, }); let ComputedOnlyFeatureSchema = createPropertySchema({ diff --git a/app/imports/api/properties/Items.js b/app/imports/api/properties/Items.js index 373a6054..2183d567 100644 --- a/app/imports/api/properties/Items.js +++ b/app/imports/api/properties/Items.js @@ -6,15 +6,15 @@ const ItemSchema = createPropertySchema({ name: { type: String, optional: true, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, // Plural name of the item, if there is more than one plural: { type: String, optional: true, - max: STORAGE_LIMITS.name, + max: STORAGE_LIMITS.name, }, - description: { + description: { type: 'inlineCalculationFieldToCompute', optional: true, }, @@ -28,20 +28,20 @@ const ItemSchema = createPropertySchema({ weight: { type: Number, min: 0, - optional: true, + optional: true, }, // Value per item in the stack, in gold pieces value: { type: Number, min: 0, - optional: true, + optional: true, }, // If this item is equipped, it requires attunement requiresAttunement: { type: Boolean, optional: true, }, - attuned: { + attuned: { type: Boolean, optional: true, }, @@ -58,14 +58,14 @@ const ItemSchema = createPropertySchema({ }); let ComputedOnlyItemSchema = createPropertySchema({ - description: { - type: 'computedOnlyInlineCalculationField', - optional: true, - }, + description: { + type: 'computedOnlyInlineCalculationField', + optional: true, + }, }); const ComputedItemSchema = new SimpleSchema() - .extend(ItemSchema) - .extend(ComputedOnlyItemSchema); + .extend(ItemSchema) + .extend(ComputedOnlyItemSchema); export { ItemSchema, ComputedItemSchema, ComputedOnlyItemSchema }; diff --git a/app/imports/api/properties/Notes.js b/app/imports/api/properties/Notes.js index dd76d906..1e738b08 100644 --- a/app/imports/api/properties/Notes.js +++ b/app/imports/api/properties/Notes.js @@ -3,19 +3,19 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; let NoteSchema = createPropertySchema({ - name: { - type: String, - optional: true, + name: { + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, - summary: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, + }, + summary: { + type: 'inlineCalculationFieldToCompute', + optional: true, + }, description: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, + type: 'inlineCalculationFieldToCompute', + optional: true, + }, }); let ComputedOnlyNoteSchema = createPropertySchema({ diff --git a/app/imports/api/properties/Proficiencies.js b/app/imports/api/properties/Proficiencies.js index 8e8246ac..e79276ff 100644 --- a/app/imports/api/properties/Proficiencies.js +++ b/app/imports/api/properties/Proficiencies.js @@ -2,28 +2,28 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; let ProficiencySchema = new SimpleSchema({ - name: { - type: String, - optional: true, + name: { + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, - // The variableNames of the skills, tags, or attributes to apply proficiency to - stats: { - type: Array, - defaultValue: [], + }, + // The variableNames of the skills, tags, or attributes to apply proficiency to + stats: { + type: Array, + defaultValue: [], maxCount: STORAGE_LIMITS.statsToTarget, - }, - 'stats.$': { - type: String, + }, + 'stats.$': { + type: String, max: STORAGE_LIMITS.variableName, - }, - // A number representing how proficient the character is + }, + // A number representing how proficient the character is // where 0.49 is half rounded down and 0.5 is half rounded up - value: { - type: Number, - allowedValues: [0.49, 0.5, 1, 2], - defaultValue: 1, - }, + value: { + type: Number, + allowedValues: [0.49, 0.5, 1, 2], + defaultValue: 1, + }, }); const ComputedOnlyProficiencySchema = new SimpleSchema({}); diff --git a/app/imports/api/properties/Rolls.js b/app/imports/api/properties/Rolls.js index 03e819a4..7a2c5eeb 100644 --- a/app/imports/api/properties/Rolls.js +++ b/app/imports/api/properties/Rolls.js @@ -23,14 +23,14 @@ import createPropertySchema from '/imports/api/properties/subSchemas/createPrope */ let RollSchema = createPropertySchema({ name: { - type: String, + type: String, defaultValue: 'New Roll', max: STORAGE_LIMITS.name, - }, + }, // The technical, lowercase, single-word name used in formulae variableName: { type: String, - regEx: VARIABLE_NAME_REGEX, + regEx: VARIABLE_NAME_REGEX, min: 2, defaultValue: 'newRoll', max: STORAGE_LIMITS.variableName, diff --git a/app/imports/api/properties/SavingThrows.js b/app/imports/api/properties/SavingThrows.js index 05210a53..d0045187 100644 --- a/app/imports/api/properties/SavingThrows.js +++ b/app/imports/api/properties/SavingThrows.js @@ -16,14 +16,14 @@ let SavingThrowSchema = createPropertySchema({ optional: true, }, // Who this saving throw applies to - target: { - type: String, + target: { + type: String, defaultValue: 'target', - allowedValues: [ + allowedValues: [ 'self', 'target', ], - }, + }, // The variable name of save to roll stat: { type: String, diff --git a/app/imports/api/properties/Skills.js b/app/imports/api/properties/Skills.js index d9f04791..a2083cdf 100644 --- a/app/imports/api/properties/Skills.js +++ b/app/imports/api/properties/Skills.js @@ -9,10 +9,10 @@ import createPropertySchema from '/imports/api/properties/subSchemas/createPrope */ let SkillSchema = createPropertySchema({ name: { - type: String, - optional: true, + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, + }, // The technical, lowercase, single-word name used in formulae // Ignored for skilltype = save variableName: { @@ -22,33 +22,33 @@ let SkillSchema = createPropertySchema({ max: STORAGE_LIMITS.variableName, optional: true, }, - // The variable name of the ability this skill relies on + // The variable name of the ability this skill relies on ability: { type: String, optional: true, max: STORAGE_LIMITS.variableName, }, - // What type of skill is this + // What type of skill is this skillType: { type: String, allowedValues: [ 'skill', 'save', - 'check', + 'check', 'tool', 'weapon', 'armor', 'language', - 'utility', //not displayed anywhere + 'utility', //not displayed anywhere ], defaultValue: 'skill', }, - // The base proficiency of this skill - baseProficiency: { - type: Number, - optional: true, + // The base proficiency of this skill + baseProficiency: { + type: Number, + optional: true, allowedValues: [0.49, 0.5, 1, 2], - }, + }, // The starting value, before effects baseValue: { type: 'fieldToCompute', @@ -56,16 +56,16 @@ let SkillSchema = createPropertySchema({ }, // Description of what the skill is used for description: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, + type: 'inlineCalculationFieldToCompute', + optional: true, + }, }); let ComputedOnlySkillSchema = createPropertySchema({ - // Computed value of skill to be added to skill rolls + // Computed value of skill to be added to skill rolls value: { type: Number, - defaultValue: 0, + defaultValue: 0, optional: true, removeBeforeCompute: true, }, @@ -75,33 +75,33 @@ let ComputedOnlySkillSchema = createPropertySchema({ optional: true, }, description: { - type: 'computedOnlyInlineCalculationField', - optional: true, - }, - // Computed value added by the ability - abilityMod: { - type: SimpleSchema.Integer, - optional: true, + type: 'computedOnlyInlineCalculationField', + optional: true, + }, + // Computed value added by the ability + abilityMod: { + type: SimpleSchema.Integer, + optional: true, removeBeforeCompute: true, - }, - // Computed advantage/disadvantage + }, + // Computed advantage/disadvantage advantage: { type: SimpleSchema.Integer, optional: true, allowedValues: [-1, 0, 1], removeBeforeCompute: true, }, - // Computed bonus to passive checks + // Computed bonus to passive checks passiveBonus: { type: Number, optional: true, removeBeforeCompute: true, }, - // Computed proficiency multiplier + // Computed proficiency multiplier proficiency: { type: Number, allowedValues: [0, 0.49, 0.5, 1, 2], - defaultValue: 0, + defaultValue: 0, removeBeforeCompute: true, }, // Compiled text of all conditional benefits @@ -113,7 +113,7 @@ let ComputedOnlySkillSchema = createPropertySchema({ 'conditionalBenefits.$': { type: String, }, - // Computed number of things forcing this skill to fail + // Computed number of things forcing this skill to fail fail: { type: SimpleSchema.Integer, optional: true, diff --git a/app/imports/api/properties/SpellLists.js b/app/imports/api/properties/SpellLists.js index c4911cf0..01434ea2 100644 --- a/app/imports/api/properties/SpellLists.js +++ b/app/imports/api/properties/SpellLists.js @@ -3,17 +3,17 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; let SpellListSchema = createPropertySchema({ - name: { - type: String, - optional: true, + name: { + type: String, + optional: true, max: STORAGE_LIMITS.name, - }, + }, description: { - type: 'inlineCalculationFieldToCompute', - optional: true, - }, - // Calculation of how many spells in this list can be prepared - maxPrepared: { + type: 'inlineCalculationFieldToCompute', + optional: true, + }, + // Calculation of how many spells in this list can be prepared + maxPrepared: { type: 'fieldToCompute', optional: true, }, diff --git a/app/imports/api/properties/Spells.js b/app/imports/api/properties/Spells.js index 304e16a3..bcb4ee3b 100644 --- a/app/imports/api/properties/Spells.js +++ b/app/imports/api/properties/Spells.js @@ -14,88 +14,88 @@ const magicSchools = [ ]; let SpellSchema = new SimpleSchema({}) -.extend(ActionSchema) -.extend({ - name: { - type: String, - optional: true, - max: STORAGE_LIMITS.name, - }, - // If it's always prepared, it doesn't count against the number of spells - // prepared in a spell list, and enabled should be true - alwaysPrepared: { - type: Boolean, - optional: true, - }, - prepared: { - type: Boolean, - optional: true, - }, - // This spell ignores spell slot rules - castWithoutSpellSlots: { - type: Boolean, - optional: true, - }, - hasAttackRoll: { - type: Boolean, - optional: true, - }, - castingTime: { - type: String, - optional: true, - defaultValue: 'action', - max: STORAGE_LIMITS.spellDetail, - }, - range: { - type: String, - optional: true, - max: STORAGE_LIMITS.spellDetail, - }, - duration: { - type: String, - optional: true, - defaultValue: 'Instantaneous', - max: STORAGE_LIMITS.spellDetail, - }, - verbal: { - type: Boolean, - optional: true, - }, - somatic: { - type: Boolean, - optional: true, - }, - concentration: { - type: Boolean, - optional: true, - }, - material: { - type: String, - optional: true, - max: STORAGE_LIMITS.spellDetail, - }, - ritual: { - type: Boolean, - optional: true, - }, - level: { - type: SimpleSchema.Integer, - defaultValue: 1, - max: 9, - min: 0, - }, - school: { - type: String, - defaultValue: 'abjuration', - allowedValues: magicSchools, - }, -}); + .extend(ActionSchema) + .extend({ + name: { + type: String, + optional: true, + max: STORAGE_LIMITS.name, + }, + // If it's always prepared, it doesn't count against the number of spells + // prepared in a spell list, and enabled should be true + alwaysPrepared: { + type: Boolean, + optional: true, + }, + prepared: { + type: Boolean, + optional: true, + }, + // This spell ignores spell slot rules + castWithoutSpellSlots: { + type: Boolean, + optional: true, + }, + hasAttackRoll: { + type: Boolean, + optional: true, + }, + castingTime: { + type: String, + optional: true, + defaultValue: 'action', + max: STORAGE_LIMITS.spellDetail, + }, + range: { + type: String, + optional: true, + max: STORAGE_LIMITS.spellDetail, + }, + duration: { + type: String, + optional: true, + defaultValue: 'Instantaneous', + max: STORAGE_LIMITS.spellDetail, + }, + verbal: { + type: Boolean, + optional: true, + }, + somatic: { + type: Boolean, + optional: true, + }, + concentration: { + type: Boolean, + optional: true, + }, + material: { + type: String, + optional: true, + max: STORAGE_LIMITS.spellDetail, + }, + ritual: { + type: Boolean, + optional: true, + }, + level: { + type: SimpleSchema.Integer, + defaultValue: 1, + max: 9, + min: 0, + }, + school: { + type: String, + defaultValue: 'abjuration', + allowedValues: magicSchools, + }, + }); const ComputedOnlySpellSchema = new SimpleSchema() - .extend(ComputedOnlyActionSchema); + .extend(ComputedOnlyActionSchema); const ComputedSpellSchema = new SimpleSchema() - .extend(SpellSchema) - .extend(ComputedOnlySpellSchema); + .extend(SpellSchema) + .extend(ComputedOnlySpellSchema); export { SpellSchema, ComputedOnlySpellSchema, ComputedSpellSchema }; diff --git a/app/imports/api/properties/Toggles.js b/app/imports/api/properties/Toggles.js index 7a76d061..755ed89b 100644 --- a/app/imports/api/properties/Toggles.js +++ b/app/imports/api/properties/Toggles.js @@ -41,7 +41,7 @@ const ComputedOnlyToggleSchema = createPropertySchema({ }); const ComputedToggleSchema = new SimpleSchema() - .extend(ComputedOnlyToggleSchema) - .extend(ToggleSchema); + .extend(ComputedOnlyToggleSchema) + .extend(ToggleSchema); export { ToggleSchema, ComputedOnlyToggleSchema, ComputedToggleSchema }; diff --git a/app/imports/api/properties/subSchemas/AdjustmentSchema.js b/app/imports/api/properties/subSchemas/AdjustmentSchema.js index 04031e2a..5ca96137 100644 --- a/app/imports/api/properties/subSchemas/AdjustmentSchema.js +++ b/app/imports/api/properties/subSchemas/AdjustmentSchema.js @@ -5,31 +5,31 @@ const AdjustmentSchema = new SimpleSchema({ _id: { type: String, regEx: SimpleSchema.RegEx.Id, - autoValue(){ + autoValue() { if (!this.isSet) return Random.id(); } }, - // The roll that determines how much to change the attribute + // The roll that determines how much to change the attribute adjustment: { type: String, optional: true, defaultValue: '1', }, - // Who this adjustment applies to - target: { - type: String, + // Who this adjustment applies to + target: { + type: String, defaultValue: 'every', - allowedValues: [ + allowedValues: [ 'self', // the character who took the action 'each', // rolled once for `each` target 'every', // rolled once and applied to `every` target ], - }, - // The stat this rolls applies to, if damage type is set, this is ignored - stat: { - type: String, + }, + // The stat this rolls applies to, if damage type is set, this is ignored + stat: { + type: String, optional: true, - }, + }, }); export default AdjustmentSchema; diff --git a/app/imports/api/properties/subSchemas/ErrorSchema.js b/app/imports/api/properties/subSchemas/ErrorSchema.js index 87835150..41635874 100644 --- a/app/imports/api/properties/subSchemas/ErrorSchema.js +++ b/app/imports/api/properties/subSchemas/ErrorSchema.js @@ -6,10 +6,10 @@ const ErrorSchema = new SimpleSchema({ type: String, max: STORAGE_LIMITS.errorMessage, }, - type: { + type: { type: String, max: STORAGE_LIMITS.name, - }, + }, }); export default ErrorSchema; diff --git a/app/imports/api/properties/subSchemas/InlineComputationSchema.js b/app/imports/api/properties/subSchemas/InlineComputationSchema.js index e220a3aa..14a33e75 100644 --- a/app/imports/api/properties/subSchemas/InlineComputationSchema.js +++ b/app/imports/api/properties/subSchemas/InlineComputationSchema.js @@ -3,7 +3,7 @@ import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; const InlineComputationSchema = new SimpleSchema({ - // The part between bracers {} + // The part between bracers {} calculation: { type: String, max: STORAGE_LIMITS.calculation, diff --git a/app/imports/api/properties/subSchemas/RollResultsSchema.js b/app/imports/api/properties/subSchemas/RollResultsSchema.js index 1d555ddc..8aea32e9 100644 --- a/app/imports/api/properties/subSchemas/RollResultsSchema.js +++ b/app/imports/api/properties/subSchemas/RollResultsSchema.js @@ -1,11 +1,11 @@ import SimpleSchema from 'simpl-schema'; import ResultsSchema from '/imports/api/properties/subSchemas/ResultsSchema.js'; -let RollResultsSchema = new SimpleSchema ({ +let RollResultsSchema = new SimpleSchema({ _id: { type: String, regEx: SimpleSchema.RegEx.Id, - autoValue(){ + autoValue() { if (!this.isSet) return Random.id(); } }, @@ -17,9 +17,9 @@ let RollResultsSchema = new SimpleSchema ({ optional: true, }, results: { - type: ResultsSchema, - defaultValue: {}, - }, + type: ResultsSchema, + defaultValue: {}, + }, }); -export default RollResultsSchema ; +export default RollResultsSchema; diff --git a/app/imports/api/sharing/SharingSchema.js b/app/imports/api/sharing/SharingSchema.js index 77e5f939..a22da7cd 100644 --- a/app/imports/api/sharing/SharingSchema.js +++ b/app/imports/api/sharing/SharingSchema.js @@ -3,7 +3,7 @@ import '/imports/api/sharing/sharing.js'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; let SharingSchema = new SimpleSchema({ - owner: { + owner: { type: String, regEx: SimpleSchema.RegEx.Id, index: 1 @@ -12,7 +12,7 @@ let SharingSchema = new SimpleSchema({ type: Array, defaultValue: [], index: 1, - maxCount: STORAGE_LIMITS.readersCount, + maxCount: STORAGE_LIMITS.readersCount, }, 'readers.$': { type: String, @@ -22,7 +22,7 @@ let SharingSchema = new SimpleSchema({ type: Array, defaultValue: [], index: 1, - maxCount: STORAGE_LIMITS.writersCount, + maxCount: STORAGE_LIMITS.writersCount, }, 'writers.$': { type: String, diff --git a/app/imports/api/sharing/sharing.js b/app/imports/api/sharing/sharing.js index d026d879..f6c8d8b7 100644 --- a/app/imports/api/sharing/sharing.js +++ b/app/imports/api/sharing/sharing.js @@ -9,8 +9,8 @@ import { getUserTier } from '/imports/api/users/patreon/tiers.js'; const setPublic = new ValidatedMethod({ name: 'sharing.setPublic', - validate: new SimpleSchema({ - docRef: RefSchema, + validate: new SimpleSchema({ + docRef: RefSchema, isPublic: { type: Boolean }, }).validator(), mixins: [RateLimiterMixin], @@ -18,19 +18,19 @@ const setPublic = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({docRef, isPublic}){ - let doc = fetchDocByRef(docRef); - assertOwnership(doc, this.userId); - return getCollectionByName(docRef.collection).update(docRef.id, { - $set: {public: isPublic}, + run({ docRef, isPublic }) { + let doc = fetchDocByRef(docRef); + assertOwnership(doc, this.userId); + return getCollectionByName(docRef.collection).update(docRef.id, { + $set: { public: isPublic }, }); - }, + }, }); const updateUserSharePermissions = new ValidatedMethod({ name: 'sharing.updateUserSharePermissions', - validate: new SimpleSchema({ - docRef: RefSchema, + validate: new SimpleSchema({ + docRef: RefSchema, userId: { type: String, regEx: SimpleSchema.RegEx.Id, @@ -45,40 +45,40 @@ const updateUserSharePermissions = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({docRef, userId, role}){ - let doc = fetchDocByRef(docRef); - if (role === 'none'){ + run({ docRef, userId, role }) { + let doc = fetchDocByRef(docRef); + if (role === 'none') { // only assert ownership if you aren't removing yourself - if (this.userId !== userId){ + if (this.userId !== userId) { assertOwnership(doc, this.userId); } return getCollectionByName(docRef.collection).update(docRef.id, { $pullAll: { readers: userId, writers: userId }, }); } - if (doc.owner === userId){ + if (doc.owner === userId) { throw new Meteor.Error('Sharing update failed', - 'User is already the owner of this document'); + 'User is already the owner of this document'); } assertOwnership(doc, this.userId); - if (role === 'reader'){ + if (role === 'reader') { return getCollectionByName(docRef.collection).update(docRef.id, { $addToSet: { readers: userId }, $pullAll: { writers: userId }, }); - } else if (role === 'writer'){ + } else if (role === 'writer') { return getCollectionByName(docRef.collection).update(docRef.id, { $addToSet: { writers: userId }, $pullAll: { readers: userId }, }); } - }, + }, }); const transferOwnership = new ValidatedMethod({ name: 'sharing.transferOwnership', - validate: new SimpleSchema({ - docRef: RefSchema, + validate: new SimpleSchema({ + docRef: RefSchema, userId: { type: String, regEx: SimpleSchema.RegEx.Id, @@ -89,31 +89,31 @@ const transferOwnership = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({docRef, userId}){ + run({ docRef, userId }) { let doc = fetchDocByRef(docRef); assertOwnership(doc, this.userId); let collection = getCollectionByName(docRef.collection); let tier = getUserTier(userId); - if (docRef.collection === 'creatures'){ + if (docRef.collection === 'creatures') { let currentCharacterCount = collection.find({ owner: userId, }, { - fields: {_id: 1}, + fields: { _id: 1 }, }).count(); if ( tier.characterSlots !== -1 && currentCharacterCount >= tier.characterSlots - ){ + ) { throw new Meteor.Error('Sharing.methods.transferOwnership.denied', - 'The new owner is already at their character limit') + 'The new owner is already at their character limit') } - } else if (docRef.collection === 'libraries'){ - if (!tier.paidBenefits){ + } else if (docRef.collection === 'libraries') { + if (!tier.paidBenefits) { throw new Meteor.Error('Sharing.methods.transferOwnership.denied', - 'The new owner\'s Patreon tier does not have access to library ownership'); + 'The new owner\'s Patreon tier does not have access to library ownership'); } } @@ -123,10 +123,10 @@ const transferOwnership = new ValidatedMethod({ }); // Then make the user the owner and the current owner a writer return collection.update(docRef.id, { - $set: {owner: userId}, + $set: { owner: userId }, $addToSet: { writers: this.userId }, }); - }, + }, }); export { setPublic, updateUserSharePermissions, transferOwnership }; diff --git a/app/imports/api/tabletop/Messages.js b/app/imports/api/tabletop/Messages.js index b2dc0280..634f32d9 100644 --- a/app/imports/api/tabletop/Messages.js +++ b/app/imports/api/tabletop/Messages.js @@ -51,21 +51,21 @@ const sendMessage = new ValidatedMethod({ timeInterval: 5000, }, - run({content, tabletopId}) { + run({ content, tabletopId }) { let user = Meteor.user(); if (!user) { throw new Meteor.Error('messages.send.denied', - 'You need to be logged in to send a message'); + 'You need to be logged in to send a message'); } assertUserInTabletop(tabletopId, this.userId); return Messages.insert({ - content, + content, tabletopId, timestamp: new Date(), userId: user._id, username: user.username, - }); + }); }, }); @@ -87,24 +87,24 @@ const removeMessages = new ValidatedMethod({ timeInterval: 5000, }, - run({messageId, tabletopId}) { + run({ messageId, tabletopId }) { if (!this.userId) { throw new Meteor.Error('messages.remove.denied', - 'You need to be logged in to remove a tabletop'); + 'You need to be logged in to remove a tabletop'); } let message = Messages.findOne(messageId); let tabletop = Tabletops.findOne(message.tabletopId); - if (this.userId !== message.userId && this.userId !== tabletop.gameMaster){ + if (this.userId !== message.userId && this.userId !== tabletop.gameMaster) { throw new Meteor.Error('messages.remove.denied', - 'You don\'t have permission to remove this message'); + 'You don\'t have permission to remove this message'); } let removed = Messages.remove({ - _id: messageId, - }); + _id: messageId, + }); Creatures.update({ tabletop: tabletopId, }, { - $unset: {tabletop: 1}, + $unset: { tabletop: 1 }, }); return removed; }, diff --git a/app/imports/api/tabletop/methods/insertTabletop.js b/app/imports/api/tabletop/methods/insertTabletop.js index 0857031a..62ad2156 100644 --- a/app/imports/api/tabletop/methods/insertTabletop.js +++ b/app/imports/api/tabletop/methods/insertTabletop.js @@ -19,14 +19,14 @@ const insertTabletop = new ValidatedMethod({ run() { if (!this.userId) { throw new Meteor.Error('tabletops.insert.denied', - 'You need to be logged in to insert a tabletop'); + 'You need to be logged in to insert a tabletop'); } assertUserHasPaidBenefits(this.userId); assertAdmin(this.userId); return Tabletops.insert({ - gameMaster: this.userId, - }); + gameMaster: this.userId, + }); }, }); diff --git a/app/imports/api/tabletop/methods/removeTabletop.js b/app/imports/api/tabletop/methods/removeTabletop.js index 633cc6d0..4636eb4b 100644 --- a/app/imports/api/tabletop/methods/removeTabletop.js +++ b/app/imports/api/tabletop/methods/removeTabletop.js @@ -24,22 +24,22 @@ const removeTabletop = new ValidatedMethod({ timeInterval: 5000, }, - run({tabletopId}) { + run({ tabletopId }) { if (!this.userId) { throw new Meteor.Error('tabletops.remove.denied', - 'You need to be logged in to remove a tabletop'); + 'You need to be logged in to remove a tabletop'); } assertUserHasPaidBenefits(this.userId); assertUserIsTabletopOwner(tabletopId, this.userId); assertAdmin(this.userId); let removed = Tabletops.remove({ - _id: tabletopId, - }); + _id: tabletopId, + }); Creatures.update({ tabletop: tabletopId, }, { - $unset: {tabletop: 1}, + $unset: { tabletop: 1 }, }); return removed; }, diff --git a/app/imports/api/users/Users.js b/app/imports/api/users/Users.js index b3152af8..40e50311 100644 --- a/app/imports/api/users/Users.js +++ b/app/imports/api/users/Users.js @@ -75,7 +75,7 @@ const userSchema = new SimpleSchema({ }, 'subscribedLibraries.$': { type: String, - regEx: SimpleSchema.RegEx.Id, + regEx: SimpleSchema.RegEx.Id, }, subscribedLibraryCollections: { type: Array, @@ -84,81 +84,81 @@ const userSchema = new SimpleSchema({ }, 'subscribedLibraryCollections.$': { type: String, - regEx: SimpleSchema.RegEx.Id, + regEx: SimpleSchema.RegEx.Id, }, - subscribedCharacters: { + subscribedCharacters: { type: Array, defaultValue: [], max: 100, }, 'subscribedCharacters.$': { type: String, - regEx: SimpleSchema.RegEx.Id, + regEx: SimpleSchema.RegEx.Id, }, fileStorageUsed: { type: Number, optional: true, }, - profile: { - type: Object, - blackbox: true, - optional: true, - }, - preferences: { - type: Object, - optional: true, - defaultValue: {}, - }, - 'preferences.swapAbilityScoresAndModifiers': { - type: Boolean, - optional: true, - }, - 'preferences.hidePropertySelectDialogHelp': { - type: Boolean, - optional: true, - }, + profile: { + type: Object, + blackbox: true, + optional: true, + }, + preferences: { + type: Object, + optional: true, + defaultValue: {}, + }, + 'preferences.swapAbilityScoresAndModifiers': { + type: Boolean, + optional: true, + }, + 'preferences.hidePropertySelectDialogHelp': { + type: Boolean, + optional: true, + }, }); Meteor.users.attachSchema(userSchema); Meteor.users.generateApiKey = new ValidatedMethod({ - name: 'users.generateApiKey', + name: 'users.generateApiKey', validate: null, - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run(){ - if(Meteor.isClient) return; + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run() { + if (Meteor.isClient) return; var user = Meteor.users.findOne(this.userId); if (!user) return; if (user && user.apiKey) return; var apiKey = Random.id(30); - Meteor.users.update(this.userId, {$set: {apiKey}}); + Meteor.users.update(this.userId, { $set: { apiKey } }); }, }); Meteor.users.setDarkMode = new ValidatedMethod({ - name: 'users.setDarkMode', + name: 'users.setDarkMode', validate: new SimpleSchema({ - darkMode: { type: Boolean }, - }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({darkMode}){ + darkMode: { type: Boolean }, + }).validator(), + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ darkMode }) { if (!this.userId) return; - Meteor.users.update(this.userId, {$set: {darkMode}}); + Meteor.users.update(this.userId, { $set: { darkMode } }); }, }); Meteor.users.sendVerificationEmail = new ValidatedMethod({ name: 'users.sendVerificationEmail', validate: new SimpleSchema({ - userId:{ + userId: { type: String, optional: true, }, @@ -166,12 +166,12 @@ Meteor.users.sendVerificationEmail = new ValidatedMethod({ type: String, }, }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({userId, address}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ userId, address }) { userId = this.userId || userId; let user = Meteor.users.findOne(userId); if (!user) { @@ -189,140 +189,140 @@ Meteor.users.sendVerificationEmail = new ValidatedMethod({ Meteor.users.canPickUsername = new ValidatedMethod({ name: 'users.canPickUsername', validate: userSchema.pick('username').validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({username}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ username }) { if (Meteor.isClient) return; let user = Accounts.findUserByUsername(username); - // You can pick your own username - if (user && user._id === this.userId){ - return false; - } + // You can pick your own username + if (user && user._id === this.userId) { + return false; + } return !!user; } }); Meteor.users.setUsername = new ValidatedMethod({ - name: 'users.setUsername', + name: 'users.setUsername', validate: userSchema.pick('username').validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({username}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ username }) { if (!this.userId) throw 'Can only set your username if logged in'; - if (Meteor.isClient) return; - return Accounts.setUsername(this.userId, username) + if (Meteor.isClient) return; + return Accounts.setUsername(this.userId, username) } }); Meteor.users.setPreference = new ValidatedMethod({ - name: 'users.setPreference', + name: 'users.setPreference', validate: new SimpleSchema({ - preference:{ - type: String, - }, - value: { - type: SimpleSchema.oneOf(Boolean), - }, - }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({preference, value}){ + preference: { + type: String, + }, + value: { + type: SimpleSchema.oneOf(Boolean), + }, + }).validator(), + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ preference, value }) { if (!this.userId) throw 'You can only set preferences once logged in'; - let prefPath = `preferences.${preference}` - if (value == true){ - return Meteor.users.update(this.userId, { - $set: {[prefPath]: true}, - }); - } else { - return Meteor.users.update(this.userId, { - $unset: {[prefPath]: 1}, - }); - } + let prefPath = `preferences.${preference}` + if (value == true) { + return Meteor.users.update(this.userId, { + $set: { [prefPath]: true }, + }); + } else { + return Meteor.users.update(this.userId, { + $unset: { [prefPath]: 1 }, + }); + } }, }); Meteor.users.subscribeToLibrary = new ValidatedMethod({ - name: 'users.subscribeToLibrary', + name: 'users.subscribeToLibrary', validate: new SimpleSchema({ - libraryId:{ + libraryId: { type: String, - regEx: SimpleSchema.RegEx.Id, + regEx: SimpleSchema.RegEx.Id, + }, + subscribe: { + type: Boolean, }, - subscribe: { - type: Boolean, - }, }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({libraryId, subscribe}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ libraryId, subscribe }) { if (!this.userId) throw 'Can only subscribe if logged in'; - if (subscribe){ - return Meteor.users.update(this.userId, { - $addToSet: {subscribedLibraries: libraryId}, - }); - } else { - return Meteor.users.update(this.userId, { - $pullAll: {subscribedLibraries: libraryId}, - }); - } + if (subscribe) { + return Meteor.users.update(this.userId, { + $addToSet: { subscribedLibraries: libraryId }, + }); + } else { + return Meteor.users.update(this.userId, { + $pullAll: { subscribedLibraries: libraryId }, + }); + } } }); Meteor.users.subscribeToLibraryCollection = new ValidatedMethod({ - name: 'users.subscribeToLibraryCollection', + name: 'users.subscribeToLibraryCollection', validate: new SimpleSchema({ - libraryCollectionId:{ + libraryCollectionId: { type: String, - regEx: SimpleSchema.RegEx.Id, + regEx: SimpleSchema.RegEx.Id, + }, + subscribe: { + type: Boolean, }, - subscribe: { - type: Boolean, - }, }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({libraryCollectionId, subscribe}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ libraryCollectionId, subscribe }) { if (!this.userId) throw 'Can only subscribe if logged in'; - if (subscribe){ - return Meteor.users.update(this.userId, { - $addToSet: {subscribedLibraryCollections: libraryCollectionId}, - }); - } else { - return Meteor.users.update(this.userId, { - $pullAll: {subscribedLibraryCollections: libraryCollectionId}, - }); - } + if (subscribe) { + return Meteor.users.update(this.userId, { + $addToSet: { subscribedLibraryCollections: libraryCollectionId }, + }); + } else { + return Meteor.users.update(this.userId, { + $pullAll: { subscribedLibraryCollections: libraryCollectionId }, + }); + } } }); Meteor.users.findUserByUsernameOrEmail = new ValidatedMethod({ name: 'users.findUserByUsernameOrEmail', validate: new SimpleSchema({ - usernameOrEmail:{ + usernameOrEmail: { type: String, }, }).validator(), - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - run({usernameOrEmail}){ + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({ usernameOrEmail }) { if (Meteor.isClient) return; let user = Accounts.findUserByUsername(usernameOrEmail) || Accounts.findUserByEmail(usernameOrEmail); diff --git a/app/imports/api/users/methods/addEmail.js b/app/imports/api/users/methods/addEmail.js index af8e81f6..6abb2435 100644 --- a/app/imports/api/users/methods/addEmail.js +++ b/app/imports/api/users/methods/addEmail.js @@ -3,8 +3,8 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; const addEmail = new ValidatedMethod({ - name: 'users.addEmail', - validate: new SimpleSchema({ + name: 'users.addEmail', + validate: new SimpleSchema({ email: { type: String, regEx: SimpleSchema.RegEx.Email, @@ -15,20 +15,20 @@ const addEmail = new ValidatedMethod({ numRequests: 1, timeInterval: 5000, }, - run({email}){ + run({ email }) { const userId = Meteor.userId(); const user = Meteor.users.findOne(userId); if (!user) throw new Meteor.Error('No user', - 'You must be logged in to add an email address'); - if (user.emails && user.emails.length >= 2){ + 'You must be logged in to add an email address'); + if (user.emails && user.emails.length >= 2) { throw new Meteor.Error('Emails full', - 'You may only have up to 2 email addresses per account'); + 'You may only have up to 2 email addresses per account'); } - if (Meteor.isServer){ + if (Meteor.isServer) { Accounts.addEmail(userId, email); Accounts.sendVerificationEmail(userId, email); } - } + } }); export default addEmail; diff --git a/app/imports/api/users/methods/deleteMyAccount.js b/app/imports/api/users/methods/deleteMyAccount.js index f6947bfc..5c555855 100644 --- a/app/imports/api/users/methods/deleteMyAccount.js +++ b/app/imports/api/users/methods/deleteMyAccount.js @@ -1,31 +1,31 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; -import Libraries, {removeLibaryWork} from '/imports/api/library/Libraries.js'; +import Libraries, { removeLibaryWork } from '/imports/api/library/Libraries.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js'; -import {removeCreatureWork} from '/imports/api/creature/creatures/methods/removeCreature.js'; +import { removeCreatureWork } from '/imports/api/creature/creatures/methods/removeCreature.js'; Meteor.users.deleteMyAccount = new ValidatedMethod({ - name: 'users.deleteMyAccount', - validate: null, + name: 'users.deleteMyAccount', + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 1, timeInterval: 5000, }, - run(){ + run() { let userId = Meteor.userId(); if (!userId) throw new Meteor.Error('No user', 'You must be logged in to delete your account'); // Delete all creatures - let creatures = Creatures.find({owner: userId}, {fields: {_id: 1}}).fetch(); + let creatures = Creatures.find({ owner: userId }, { fields: { _id: 1 } }).fetch(); creatures.forEach(creature => removeCreatureWork(creature._id)); // Remove permissions from all creatures Creatures.update({ $or: [ - {writers: userId}, - {readers: userId}, + { writers: userId }, + { readers: userId }, ], }, { $pull: { @@ -37,14 +37,14 @@ Meteor.users.deleteMyAccount = new ValidatedMethod({ }); // Delete all libraries - let libraries = Libraries.find({owner: userId}, {fields: {_id: 1}}).fetch(); + let libraries = Libraries.find({ owner: userId }, { fields: { _id: 1 } }).fetch(); libraries.forEach(library => removeLibaryWork(library._id)); // Remove permissions from all creatures Libraries.update({ $or: [ - {writers: userId}, - {readers: userId}, + { writers: userId }, + { readers: userId }, ], }, { $pull: { @@ -57,5 +57,5 @@ Meteor.users.deleteMyAccount = new ValidatedMethod({ // delete the account Meteor.users.remove(userId); - } + } }); diff --git a/app/imports/api/users/methods/removeEmail.js b/app/imports/api/users/methods/removeEmail.js index 86ffb822..06a14281 100644 --- a/app/imports/api/users/methods/removeEmail.js +++ b/app/imports/api/users/methods/removeEmail.js @@ -3,8 +3,8 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; const removeEmail = new ValidatedMethod({ - name: 'users.removeEmail', - validate: new SimpleSchema({ + name: 'users.removeEmail', + validate: new SimpleSchema({ email: { type: String, regEx: SimpleSchema.RegEx.Email, @@ -15,23 +15,23 @@ const removeEmail = new ValidatedMethod({ numRequests: 1, timeInterval: 5000, }, - run({email}){ + run({ email }) { const userId = Meteor.userId(); const user = Meteor.users.findOne(userId); if (!user) throw new Meteor.Error('No user', - 'You must be logged in to remove an email address'); - if (!user.emails){ + 'You must be logged in to remove an email address'); + if (!user.emails) { throw new Meteor.Error('No email to remove', - 'No email addresses are associated with this account'); + 'No email addresses are associated with this account'); } - if (user.emails.length == 1){ + if (user.emails.length == 1) { throw new Meteor.Error('Can\'t remove last email', - 'You may not remove the last email address from your account'); + 'You may not remove the last email address from your account'); } - if (Meteor.isServer){ + if (Meteor.isServer) { Accounts.removeEmail(userId, email); } - } + } }); export default removeEmail; diff --git a/app/imports/migrations/methods/getVersion.js b/app/imports/migrations/methods/getVersion.js index 8b67d5fe..fdff2ab6 100644 --- a/app/imports/migrations/methods/getVersion.js +++ b/app/imports/migrations/methods/getVersion.js @@ -10,7 +10,7 @@ const dbVersionToGitVersion = { const getVersion = new ValidatedMethod({ name: 'admin.getVersion', - validate: null, + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, diff --git a/app/imports/migrations/methods/migrateTo.js b/app/imports/migrations/methods/migrateTo.js index f61fb9b3..98e1cf66 100644 --- a/app/imports/migrations/methods/migrateTo.js +++ b/app/imports/migrations/methods/migrateTo.js @@ -6,7 +6,7 @@ import { Migrations } from 'meteor/percolate:migrations'; const migrateTo = new ValidatedMethod({ name: 'admin.migrateTo', - validate: new SimpleSchema({ + validate: new SimpleSchema({ version: { type: SimpleSchema.oneOf( SimpleSchema.Integer, @@ -19,7 +19,7 @@ const migrateTo = new ValidatedMethod({ numRequests: 1, timeInterval: 10000, }, - run({version}) { + run({ version }) { if (Meteor.isClient) return; assertAdmin(this.userId); Migrations.migrateTo(version); diff --git a/app/imports/migrations/methods/validateDatabase.js b/app/imports/migrations/methods/validateDatabase.js index c555f3c5..09138f4f 100644 --- a/app/imports/migrations/methods/validateDatabase.js +++ b/app/imports/migrations/methods/validateDatabase.js @@ -4,7 +4,7 @@ import { assertAdmin } from '/imports/api/sharing/sharingPermissions.js'; const validateDatabase = new ValidatedMethod({ name: 'validateDatabase', - validate: null, + validate: null, mixins: [RateLimiterMixin], rateLimit: { numRequests: 1, @@ -23,8 +23,8 @@ const validateDatabase = new ValidatedMethod({ const schema = collection.instance.simpleSchema(doc); let cleanDoc = schema.clean(doc); try { - schema.validate(cleanDoc, {modifier: false}); - } catch (e){ + schema.validate(cleanDoc, { modifier: false }); + } catch (e) { console.log(collection.name, doc._id, e.message || e.reason || e.toString()); } }); diff --git a/app/imports/parser/grammar.ne b/app/imports/parser/grammar.ne index e2f7d1bf..51d1ece2 100644 --- a/app/imports/parser/grammar.ne +++ b/app/imports/parser/grammar.ne @@ -2,7 +2,7 @@ @{% import node from './parseTree/_index.js'; - import moo from 'moo'; + import moo from 'moo'; const lexer = moo.compile({ number: /[0-9]+(?:\.[0-9]+)?/, diff --git a/app/imports/parser/parseTree/index.js b/app/imports/parser/parseTree/index.js index 64f9945c..d866cc38 100644 --- a/app/imports/parser/parseTree/index.js +++ b/app/imports/parser/parseTree/index.js @@ -2,23 +2,23 @@ import resolve, { traverse, toString, map } from '../resolve'; import error from './error'; const indexNode = { - create({array, index}) { - return { + create({ array, index }) { + return { parseType: 'index', array, index, } }, - resolve(fn, node, scope, context){ - let {result: index} = resolve(fn, node.index, scope, context); - let {result: array} = resolve(fn, node.array, scope, context); + resolve(fn, node, scope, context) { + let { result: index } = resolve(fn, node.index, scope, context); + let { result: array } = resolve(fn, node.array, scope, context); if ( index.valueType === 'number' && Number.isInteger(index.value) && array.parseType === 'array' - ){ - if (index.value < 1 || index.value > array.values.length){ + ) { + if (index.value < 1 || index.value > array.values.length) { context.error({ type: 'warning', message: `Index of ${index.value} is out of range for an array` + @@ -26,11 +26,11 @@ const indexNode = { }); } let selection = array.values[index.value - 1]; - if (selection){ + if (selection) { return resolve(fn, selection, scope, context); } - } else if (fn === 'reduce'){ - if (array.parseType !== 'array'){ + } else if (fn === 'reduce') { + if (array.parseType !== 'array') { const message = `Can not get the index of a non-array node: ${toString(node.array)} = ${toString(array)}` context.error(message); return { @@ -40,7 +40,7 @@ const indexNode = { }), context, }; - } else if (!index.isInteger){ + } else if (!index.isInteger) { const message = `${toString(array)} is not an integer index of the array` context.error(message); return { @@ -60,17 +60,17 @@ const indexNode = { context, }; }, - toString(node){ + toString(node) { return `${toString(node.array)}[${toString(node.index)}]`; }, - traverse(node, fn){ + traverse(node, fn) { fn(node); traverse(node.array, fn); traverse(node.index, fn); }, - map(node, fn){ + map(node, fn) { const resultingNode = fn(node); - if (resultingNode === node){ + if (resultingNode === node) { node.array = map(node.array, fn); node.index = map(node.index, fn); } diff --git a/app/imports/parser/parseTree/rollArray.js b/app/imports/parser/parseTree/rollArray.js index d8b0c016..969b948d 100644 --- a/app/imports/parser/parseTree/rollArray.js +++ b/app/imports/parser/parseTree/rollArray.js @@ -1,24 +1,24 @@ import constant from './constant.js'; const rollArray = { - create({values, diceSize, diceNum}) { - return { + create({ values, diceSize, diceNum }) { + return { parseType: 'rollArray', values, diceSize, diceNum, }; }, - compile(node, scope, context){ + compile(node, scope, context) { return { result: node, context }; }, - toString(node){ + toString(node) { return `${node.diceNum || ''}d${node.diceSize} [ ${node.values.join(', ')} ]`; }, - reduce(node, scope, context){ + reduce(node, scope, context) { const total = node.values.reduce((a, b) => a + b, 0); return { result: constant.create({ diff --git a/app/imports/server/cron/deleteSoftRemovedDocuments.js b/app/imports/server/cron/deleteSoftRemovedDocuments.js index 835e3773..22a1d5ad 100644 --- a/app/imports/server/cron/deleteSoftRemovedDocuments.js +++ b/app/imports/server/cron/deleteSoftRemovedDocuments.js @@ -6,7 +6,7 @@ import { SyncedCron } from 'meteor/littledata:synced-cron'; Meteor.startup(() => { const collections = [ CreatureProperties, - LibraryNodes, + LibraryNodes, ]; /** @@ -14,15 +14,15 @@ Meteor.startup(() => { * and were not restored * @return {Number} Number of documents removed */ - const deleteOldSoftRemovedDocs = function(){ + const deleteOldSoftRemovedDocs = function () { const now = new Date(); - const yesterday = new Date(now.getTime() - (24 * 60 * 60 * 1000)); + const yesterday = new Date(now.getTime() - (24 * 60 * 60 * 1000)); collections.forEach(collection => { collection.remove({ removed: true, - removedAt: {$lt: yesterday} // dates *before* yesterday - }, function(error){ - if (error){ + removedAt: { $lt: yesterday } // dates *before* yesterday + }, function (error) { + if (error) { console.error(JSON.stringify(error, null, 2)); } }); @@ -31,7 +31,7 @@ Meteor.startup(() => { SyncedCron.add({ name: 'deleteSoftRemovedDocs', - schedule: function(parser) { + schedule: function (parser) { return parser.text('every 10 minutes'); }, job: deleteOldSoftRemovedDocs, @@ -42,7 +42,7 @@ Meteor.startup(() => { // Add a method to manually trigger removal Meteor.methods({ deleteOldSoftRemovedDocs() { - assertAdmin(this.userId); + assertAdmin(this.userId); this.unblock(); deleteOldSoftRemovedDocs(); }, diff --git a/app/imports/server/publications/icons.js b/app/imports/server/publications/icons.js index a289fdcf..fc5313a2 100644 --- a/app/imports/server/publications/icons.js +++ b/app/imports/server/publications/icons.js @@ -1,16 +1,16 @@ import Icons from '/imports/api/icons/Icons.js'; -Meteor.publish('sampleIcons', function(){ - return Icons.find({}, {limit: 50}); +Meteor.publish('sampleIcons', function () { + return Icons.find({}, { limit: 50 }); }); -Meteor.publish('searchIcons', function(searchValue) { +Meteor.publish('searchIcons', function (searchValue) { // Don't publish anything if there's no search value if (!searchValue) { return []; } return Icons.find( - { $text: {$search: searchValue} }, + { $text: { $search: searchValue } }, { // relevant documents have a higher score. fields: { diff --git a/app/imports/server/publications/users.js b/app/imports/server/publications/users.js index f096ccd2..b6e59e82 100644 --- a/app/imports/server/publications/users.js +++ b/app/imports/server/publications/users.js @@ -2,31 +2,33 @@ import SimpleSchema from 'simpl-schema'; import '/imports/api/users/Users.js'; import Invites from '/imports/api/users/Invites.js'; -Meteor.publish('user', function(){ - return [ - Meteor.users.find(this.userId, {fields: { - roles: 1, - username: 1, - apiKey: 1, - darkMode: 1, - subscribedLibraries: 1, - subscribedLibraryCollections: 1, - fileStorageUsed: 1, - profile: 1, - preferences: 1, - 'services.patreon.id': 1, - 'services.patreon.entitledCents': 1, - 'services.patreon.entitledCentsOverride': 1, - 'services.google.id': 1, - 'services.google.picture': 1, - 'services.google.name': 1, - 'services.google.email': 1, - 'services.google.locale': 1, - }}), +Meteor.publish('user', function () { + return [ + Meteor.users.find(this.userId, { + fields: { + roles: 1, + username: 1, + apiKey: 1, + darkMode: 1, + subscribedLibraries: 1, + subscribedLibraryCollections: 1, + fileStorageUsed: 1, + profile: 1, + preferences: 1, + 'services.patreon.id': 1, + 'services.patreon.entitledCents': 1, + 'services.patreon.entitledCentsOverride': 1, + 'services.google.id': 1, + 'services.google.picture': 1, + 'services.google.name': 1, + 'services.google.email': 1, + 'services.google.locale': 1, + } + }), Invites.find({ $or: [ - {inviter: this.userId}, - {invitee: this.userId} + { inviter: this.userId }, + { invitee: this.userId } ], }, { fields: { @@ -41,19 +43,19 @@ let userIdsSchema = new SimpleSchema({ type: Array, optional: true, }, - 'ids.$':{ + 'ids.$': { type: String, regEx: SimpleSchema.RegEx.Id, } }) -Meteor.publish('userPublicProfiles', function(ids){ - userIdsSchema.validate({ids}); - if (!this.userId || !ids) return this.ready(); - return Meteor.users.find({ - _id: {$in: ids} - },{ - fields: {username: 1}, - sort: {username: 1}, - }); +Meteor.publish('userPublicProfiles', function (ids) { + userIdsSchema.validate({ ids }); + if (!this.userId || !ids) return this.ready(); + return Meteor.users.find({ + _id: { $in: ids } + }, { + fields: { username: 1 }, + sort: { username: 1 }, + }); }); diff --git a/app/imports/ui/components/ColumnLayout.vue b/app/imports/ui/components/ColumnLayout.vue index de3e1448..3b53c998 100644 --- a/app/imports/ui/components/ColumnLayout.vue +++ b/app/imports/ui/components/ColumnLayout.vue @@ -12,41 +12,46 @@ diff --git a/app/imports/ui/components/IncrementMenu.vue b/app/imports/ui/components/IncrementMenu.vue index 6a2b954c..99c2de58 100644 --- a/app/imports/ui/components/IncrementMenu.vue +++ b/app/imports/ui/components/IncrementMenu.vue @@ -65,102 +65,103 @@ diff --git a/app/imports/ui/components/MarkdownText.vue b/app/imports/ui/components/MarkdownText.vue index b3576203..bb133d27 100644 --- a/app/imports/ui/components/MarkdownText.vue +++ b/app/imports/ui/components/MarkdownText.vue @@ -8,20 +8,20 @@ diff --git a/app/imports/ui/components/ToolbarCard.vue b/app/imports/ui/components/ToolbarCard.vue index 099a674a..9187bdf9 100644 --- a/app/imports/ui/components/ToolbarCard.vue +++ b/app/imports/ui/components/ToolbarCard.vue @@ -27,54 +27,58 @@ diff --git a/app/imports/ui/components/global/IconPicker.vue b/app/imports/ui/components/global/IconPicker.vue index 9d7dbc2b..13ef7954 100644 --- a/app/imports/ui/components/global/IconPicker.vue +++ b/app/imports/ui/components/global/IconPicker.vue @@ -87,7 +87,7 @@ export default { SvgIcon, }, mixins: [SmartInput], - props: { + props: { label: { type: String, default: 'Icon', @@ -96,39 +96,42 @@ export default { type: String, default: undefined, }, - }, - data(){return { - menu: false, - searchString: '', - icons: [], - };}, + }, + data() { + return { + menu: false, + searchString: '', + icons: [], + }; + }, watch: { - menu(value){ - if (value){ + menu(value) { + if (value) { setTimeout(() => { - if (this.$refs.iconSearchField){ + if (this.$refs.iconSearchField) { this.$refs.iconSearchField.$children[0].focus(); } }, 100); } }, }, - methods: { - search(value, ack){ + methods: { + search(value, ack) { this.searchString = value; this.icons = []; - findIcons.call({search: value}, (error, result) => { + findIcons.call({ search: value }, (error, result) => { ack(error); this.icons = result; }); }, - select(icon){ + select(icon) { this.menu = false; this.change(icon); }, - }, + }, } diff --git a/app/imports/ui/components/global/SmartCombobox.vue b/app/imports/ui/components/global/SmartCombobox.vue index 07931531..d5c985c0 100644 --- a/app/imports/ui/components/global/SmartCombobox.vue +++ b/app/imports/ui/components/global/SmartCombobox.vue @@ -21,34 +21,36 @@ diff --git a/app/imports/ui/components/global/SmartInputMixin.js b/app/imports/ui/components/global/SmartInputMixin.js index 9cf02830..245656b6 100644 --- a/app/imports/ui/components/global/SmartInputMixin.js +++ b/app/imports/ui/components/global/SmartInputMixin.js @@ -13,16 +13,18 @@ export default { context: { default: {} } }, inheritAttrs: false, - data(){ return { - error: false, - ackErrors: null, - rulesErrors: null, - focused: false, - loading: false, - dirty: false, - safeValue: this.value, - inputValue: this.value, - };}, + data() { + return { + error: false, + ackErrors: null, + rulesErrors: null, + focused: false, + loading: false, + dirty: false, + safeValue: this.value, + inputValue: this.value, + }; + }, props: { value: [String, Number, Date, Array, Object, Boolean], errorMessages: [String, Array], @@ -34,11 +36,11 @@ export default { rules: Array, }, watch: { - focused(newFocus){ + focused(newFocus) { // If the value updated while we were focused, show it now on defocus // but not if we are waiting for our own writes to get persisted // and not if there is an error in our input - if (!newFocus && !this.dirty && !this.error){ + if (!newFocus && !this.dirty && !this.error) { this.forceSafeValueUpdate(); } // Start the loading bar on defocus if the input is dirty @@ -48,118 +50,118 @@ export default { !newFocus && this.dirty && !(this.rulesErrors && this.rulesErrors.length) - ){ + ) { if (this.hasChangeListener) this.loading = true; } }, - dirty(newDirty){ + dirty(newDirty) { // Our changes were acknowledged, weren't in error, and we aren't focused, // make sure the internal value matches the database value - if (!newDirty && !this.focused && !this.error){ + if (!newDirty && !this.focused && !this.error) { this.forceSafeValueUpdate(); } }, - value(newValue){ + value(newValue) { if ( !this.focused && !(this.rulesErrors && this.rulesErrors.length) - ){ + ) { this.safeValue = newValue; } }, - safeValue(){ + safeValue() { // The safe value only gets updated from the parent, so it must be valid this.error = false; this.ackErrors = null; }, }, methods: { - input(val){ + input(val) { this.$emit('input', val); this.inputValue = val; this.dirty = true; // Apply the rules if there are any this.rulesErrors = null; - if (this.rules && this.rules.length){ + if (this.rules && this.rules.length) { this.rules.forEach(rule => { const result = rule(val); - if (typeof result === 'string'){ + if (typeof result === 'string') { if (!this.rulesErrors) this.rulesErrors = []; this.rulesErrors.push(result); } }); } - if (this.rulesErrors){ + if (this.rulesErrors) { return; } this.debouncedChange(val); }, - acknowledgeChange(error){ + acknowledgeChange(error) { this.loading = false; this.dirty = false; this.error = !!error; - if (!error){ - this.ackErrors = null; - } else if (typeof error === 'string'){ - this.ackErrors = error; - } else if (error.reason){ + if (!error) { + this.ackErrors = null; + } else if (typeof error === 'string') { + this.ackErrors = error; + } else if (error.reason) { this.ackErrors = error.reason; - } else if (error.message){ + } else if (error.message) { this.ackErrors = error.message; } else { - this.ackErrors = 'Something went wrong' - console.error(error); - } + this.ackErrors = 'Something went wrong' + console.error(error); + } }, - change(val){ + change(val) { this.dirty = true; if (this.hasChangeListener()) this.loading = true; this.$emit('change', val, this.acknowledgeChange); }, - hasChangeListener(){ + hasChangeListener() { return this.$listeners && this.$listeners.change; }, - forceSafeValueUpdate(){ + forceSafeValueUpdate() { // hack to force the value to update on the child component this.safeValue = null; this.$nextTick(() => this.safeValue = this.value); }, - focus(){ + focus() { this.$refs.input.focus(); } }, computed: { - errors(){ + errors() { let errors = this.ackErrors ? [this.ackErrors] : []; - if (Array.isArray(this.rulesErrors)){ + if (Array.isArray(this.rulesErrors)) { errors.push(...this.rulesErrors) } - if (Array.isArray(this.errorMessages)){ + if (Array.isArray(this.errorMessages)) { errors.push(...this.errorMessages); - } else if (typeof this.errorMessages === 'string' && this.errorMessages){ + } else if (typeof this.errorMessages === 'string' && this.errorMessages) { errors.push(this.errorMessages); } return errors; }, - isDisabled(){ + isDisabled() { return this.context.editPermission === false || this.disabled; }, debounceTime() { - if (Number.isFinite(this.debounce)){ + if (Number.isFinite(this.debounce)) { return this.debounce; - } else if (Number.isFinite(this.context.debounceTime)){ + } else if (Number.isFinite(this.context.debounceTime)) { return this.context.debounceTime; } else { return 750; } }, }, - created(){ + created() { this.debouncedChange = debounce(this.change, this.debounceTime); }, - beforeDestroy(){ + beforeDestroy() { this.debouncedChange.flush(); }, }; diff --git a/app/imports/ui/components/global/SmartSelect.vue b/app/imports/ui/components/global/SmartSelect.vue index 439f735b..005ea2ae 100644 --- a/app/imports/ui/components/global/SmartSelect.vue +++ b/app/imports/ui/components/global/SmartSelect.vue @@ -23,9 +23,9 @@ diff --git a/app/imports/ui/components/global/TextArea.vue b/app/imports/ui/components/global/TextArea.vue index 40722679..2fe4f8c8 100644 --- a/app/imports/ui/components/global/TextArea.vue +++ b/app/imports/ui/components/global/TextArea.vue @@ -14,15 +14,15 @@ diff --git a/app/imports/ui/components/tree/TreeNode.vue b/app/imports/ui/components/tree/TreeNode.vue index 4579c441..913a8954 100644 --- a/app/imports/ui/components/tree/TreeNode.vue +++ b/app/imports/ui/components/tree/TreeNode.vue @@ -77,134 +77,149 @@ diff --git a/app/imports/ui/components/tree/TreeNodeList.vue b/app/imports/ui/components/tree/TreeNodeList.vue index f5915ca2..1ea59678 100644 --- a/app/imports/ui/components/tree/TreeNodeList.vue +++ b/app/imports/ui/components/tree/TreeNodeList.vue @@ -33,102 +33,112 @@ diff --git a/app/imports/ui/creature/CreatureForm.vue b/app/imports/ui/creature/CreatureForm.vue index 1a0f82e0..d2ea8eeb 100644 --- a/app/imports/ui/creature/CreatureForm.vue +++ b/app/imports/ui/creature/CreatureForm.vue @@ -67,25 +67,25 @@ :value="model.settings.discordWebhook" @change="(value, ack) => $emit('change', {path: ['settings','discordWebhook'], value, ack})" /> - @@ -121,41 +121,42 @@ diff --git a/app/imports/ui/creature/CreatureFormDialog.vue b/app/imports/ui/creature/CreatureFormDialog.vue index 9a80adce..04fa4d19 100644 --- a/app/imports/ui/creature/CreatureFormDialog.vue +++ b/app/imports/ui/creature/CreatureFormDialog.vue @@ -1,5 +1,8 @@ diff --git a/app/imports/ui/creature/character/CharacterSheetToolbar.vue b/app/imports/ui/creature/character/CharacterSheetToolbar.vue index 0cafc021..0fb36161 100644 --- a/app/imports/ui/creature/character/CharacterSheetToolbar.vue +++ b/app/imports/ui/creature/character/CharacterSheetToolbar.vue @@ -11,17 +11,13 @@ dense > - + {{ $store.state.pageTitle }} - + { - if (error) { - console.error(error); - } else { - that.$router.push('/characterList'); - } - }); - } - }); - }, - unshareWithMe(){ + showCharacterForm() { + this.$store.commit('pushDialogStack', { + component: 'creature-form-dialog', + elementId: 'creature-menu', + data: { + _id: this.creatureId, + }, + }); + }, + showShareDialog() { + this.$store.commit('pushDialogStack', { + component: 'share-dialog', + elementId: 'creature-menu', + data: { + docRef: { + id: this.creatureId, + collection: 'creatures', + } + }, + }); + }, + deleteCharacter() { + let that = this; + this.$store.commit('pushDialogStack', { + component: 'delete-confirmation-dialog', + elementId: 'creature-menu', + data: { + name: this.creature.name, + typeName: 'Character' + }, + callback(confirmation) { + if (!confirmation) return; + removeCreature.call({ charId: that.creatureId }, (error) => { + if (error) { + console.error(error); + } else { + that.$router.push('/characterList'); + } + }); + } + }); + }, + unshareWithMe() { updateUserSharePermissions.call({ docRef: { collection: 'creatures', @@ -230,10 +226,10 @@ export default { }, }, meteor: { - creature(){ + creature() { return Creatures.findOne(this.creatureId); }, - editPermission(){ + editPermission() { try { assertEditPermission(this.creature, Meteor.userId()); return true; @@ -249,9 +245,11 @@ export default { .character-sheet-toolbar .v-tabs__container--grow .v-tabs__div { max-width: 120px !important; } + .character-sheet-toolbar .v-tabs__bar { background: none !important; } + .character-sheet-fab { bottom: -24px; right: 8px; diff --git a/app/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue b/app/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue index b6a2bb19..c1bfc215 100644 --- a/app/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue +++ b/app/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue @@ -16,44 +16,45 @@ diff --git a/app/imports/ui/creature/character/characterSheetTabs/InventoryTab.vue b/app/imports/ui/creature/character/characterSheetTabs/InventoryTab.vue index ad8ef5d7..ea77fddd 100644 --- a/app/imports/ui/creature/character/characterSheetTabs/InventoryTab.vue +++ b/app/imports/ui/creature/character/characterSheetTabs/InventoryTab.vue @@ -30,9 +30,7 @@ - + @@ -85,9 +83,7 @@ v-for="container in containersWithoutAncestorContainers" :key="container._id" > - + @@ -107,83 +103,87 @@ import stripFloatingPointOddities from '/imports/api/engine/computation/utility/ import CreatureVariables from '../../../../api/creature/creatures/CreatureVariables'; export default { - components: { - ColumnLayout, - ContainerCard, + components: { + ColumnLayout, + ContainerCard, ToolbarCard, ItemList, CoinValue, - }, - props: { - creatureId: { + }, + props: { + creatureId: { type: String, required: true, }, - }, - data(){ return { - organize: false, - }}, - meteor: { - containers(){ - return CreatureProperties.find({ - 'ancestors.id': this.creatureId, - type: 'container', - removed: {$ne: true}, - inactive: {$ne: true}, - }, { - sort: {order: 1}, - }); - }, - creature(){ - return Creatures.findOne(this.creatureId, {fields: { - color: 1, - variables: 1, - }}); + }, + data() { + return { + organize: false, + } + }, + meteor: { + containers() { + return CreatureProperties.find({ + 'ancestors.id': this.creatureId, + type: 'container', + removed: { $ne: true }, + inactive: { $ne: true }, + }, { + sort: { order: 1 }, + }); + }, + creature() { + return Creatures.findOne(this.creatureId, { + fields: { + color: 1, + variables: 1, + } + }); }, variables() { return CreatureVariables.findOne({ _creatureId: this.creatureId }) || {}; }, - containersWithoutAncestorContainers(){ - return CreatureProperties.find({ - 'ancestors.id': { - $eq: this.creatureId, - $nin: this.containerIds - }, - type: 'container', - removed: {$ne: true}, - inactive: {$ne: true}, - }, { - sort: {order: 1}, - }); - }, - carriedItems(){ + containersWithoutAncestorContainers() { return CreatureProperties.find({ 'ancestors.id': { - $eq: this.creatureId, - $nin: this.containerIds - }, - type: 'item', - equipped: {$ne: true}, - removed: {$ne: true}, - deactivatedByAncestor: {$ne: true}, - }, { - sort: {order: 1}, - }); + $eq: this.creatureId, + $nin: this.containerIds + }, + type: 'container', + removed: { $ne: true }, + inactive: { $ne: true }, + }, { + sort: { order: 1 }, + }); }, - equippedItems(){ + carriedItems() { return CreatureProperties.find({ 'ancestors.id': { - $eq: this.creatureId, - }, - type: 'item', + $eq: this.creatureId, + $nin: this.containerIds + }, + type: 'item', + equipped: { $ne: true }, + removed: { $ne: true }, + deactivatedByAncestor: { $ne: true }, + }, { + sort: { order: 1 }, + }); + }, + equippedItems() { + return CreatureProperties.find({ + 'ancestors.id': { + $eq: this.creatureId, + }, + type: 'item', equipped: true, - removed: {$ne: true}, - inactive: {$ne: true}, - }, { - sort: {order: 1}, - }); + removed: { $ne: true }, + inactive: { $ne: true }, + }, { + sort: { order: 1 }, + }); }, - equipmentParentRef(){ + equipmentParentRef() { return getParentRefByTag( this.creatureId, BUILT_IN_TAGS.equipment ) || getParentRefByTag( @@ -193,7 +193,7 @@ export default { collection: 'creatures' }; }, - carriedParentRef(){ + carriedParentRef() { return getParentRefByTag( this.creatureId, BUILT_IN_TAGS.carried ) || getParentRefByTag( @@ -203,30 +203,31 @@ export default { collection: 'creatures' }; }, - }, - computed: { - containerIds(){ - return this.containers.map(container => container._id); - }, - weightCarried(){ + }, + computed: { + containerIds() { + return this.containers.map(container => container._id); + }, + weightCarried() { return stripFloatingPointOddities( this.variables && this.variables.weightCarried && this.variables.weightCarried.value || 0 ); }, - }, - methods: { - clickProperty(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `tree-node-${_id}`, - data: {_id}, - }); - }, - }, + }, + methods: { + clickProperty(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: `tree-node-${_id}`, + data: { _id }, + }); + }, + }, } diff --git a/app/imports/ui/creature/character/characterSheetTabs/SpellsTab.vue b/app/imports/ui/creature/character/characterSheetTabs/SpellsTab.vue index ad87c9f5..a5e307cc 100644 --- a/app/imports/ui/creature/character/characterSheetTabs/SpellsTab.vue +++ b/app/imports/ui/creature/character/characterSheetTabs/SpellsTab.vue @@ -29,41 +29,43 @@ import SpellListCard from '/imports/ui/properties/components/spells/SpellListCar import SpellList from '/imports/ui/properties/components/spells/SpellList.vue'; export default { - components: { - ColumnLayout, + components: { + ColumnLayout, SpellList, - SpellListCard, - }, - props: { - creatureId: { + SpellListCard, + }, + props: { + creatureId: { type: String, required: true, } - }, - data(){ return { - organize: false, - }}, - meteor: { - spellLists(){ + }, + data() { + return { + organize: false, + } + }, + meteor: { + spellLists() { return CreatureProperties.find({ 'ancestors.id': this.creatureId, type: 'spellList', - removed: {$ne: true}, - inactive: {$ne: true}, + removed: { $ne: true }, + inactive: { $ne: true }, }, { - sort: {order: 1} + sort: { order: 1 } }); - }, - spellsWithoutList(){ + }, + spellsWithoutList() { return CreatureProperties.find({ 'ancestors.id': { $eq: this.creatureId, $nin: this.spellListIds, }, type: 'spell', - removed: {$ne: true}, - deactivatedByAncestor: {$ne: true}, - deactivatedByToggle: {$ne: true}, + removed: { $ne: true }, + deactivatedByAncestor: { $ne: true }, + deactivatedByToggle: { $ne: true }, }, { sort: { level: 1, @@ -71,36 +73,37 @@ export default { } }); }, - spellListsWithoutAncestorSpellLists(){ + spellListsWithoutAncestorSpellLists() { return CreatureProperties.find({ 'ancestors.id': { $eq: this.creatureId, $nin: this.spellListIds, }, type: 'spellList', - removed: {$ne: true}, - inactive: {$ne: true}, + removed: { $ne: true }, + inactive: { $ne: true }, }, { - sort: {order: 1} + sort: { order: 1 } }); - }, - }, - computed: { - spellListIds(){ - return this.spellLists.map(spellList => spellList._id); - }, - }, - methods: { - clickProperty(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `spell-list-tile-${_id}`, - data: {_id}, - }); - }, - }, + }, + }, + computed: { + spellListIds() { + return this.spellLists.map(spellList => spellList._id); + }, + }, + methods: { + clickProperty(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: `spell-list-tile-${_id}`, + data: { _id }, + }); + }, + }, } diff --git a/app/imports/ui/creature/character/characterSheetTabs/StatsTab.vue b/app/imports/ui/creature/character/characterSheetTabs/StatsTab.vue index ab4aa6fc..582a8642 100644 --- a/app/imports/ui/creature/character/characterSheetTabs/StatsTab.vue +++ b/app/imports/ui/creature/character/characterSheetTabs/StatsTab.vue @@ -1,7 +1,5 @@ diff --git a/app/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue b/app/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue index e24407fe..db6ceb72 100644 --- a/app/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue +++ b/app/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue @@ -20,7 +20,7 @@ import { getPropertyName } from '/imports/constants/PROPERTIES.js'; export default { components: { SelectablePropertyDialog, - CreaturePropertyInsertForm, + CreaturePropertyInsertForm, }, props: { forcedType: { @@ -28,21 +28,24 @@ export default { default: undefined, }, }, - data() { return { - type: undefined, - };}, - methods: { - getPropertyName, - back(){ - if (this.forcedType){ + data() { + return { + type: undefined, + }; + }, + methods: { + getPropertyName, + back() { + if (this.forcedType) { this.$store.dispatch('popDialogStack'); } else { this.type = undefined; } }, - }, + }, }; diff --git a/app/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue b/app/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue index 1910b5ee..72d0e8da 100644 --- a/app/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue +++ b/app/imports/ui/creature/creatureProperties/CreaturePropertyFromLibraryDialog.vue @@ -23,18 +23,21 @@ diff --git a/app/imports/ui/creature/experiences/ExperienceInsertDialog.vue b/app/imports/ui/creature/experiences/ExperienceInsertDialog.vue index 28756d1f..9b9ecc72 100644 --- a/app/imports/ui/creature/experiences/ExperienceInsertDialog.vue +++ b/app/imports/ui/creature/experiences/ExperienceInsertDialog.vue @@ -34,9 +34,9 @@ import schemaFormMixin from '/imports/ui/properties/forms/shared/schemaFormMixin export default { components: { - DialogBase, + DialogBase, ExperienceForm, - }, + }, mixins: [schemaFormMixin], provide: { context: { @@ -52,10 +52,10 @@ export default { type: Boolean, }, }, - data(){ + data() { let schema = ExperienceSchema.omit('creatureId'); let startingModel = {}; - if (this.startAsMilestone){ + if (this.startAsMilestone) { startingModel.levels = 1; } return { @@ -65,14 +65,14 @@ export default { debounceTime: 0, }; }, - methods:{ - insertExperience(){ + methods: { + insertExperience() { let experience = this.schema.clean(this.model); let id = insertExperience.call({ experience, creatureIds: this.creatureIds, - }, (error) => { - if (error){ + }, (error) => { + if (error) { console.error(error); } }); @@ -83,4 +83,5 @@ export default { diff --git a/app/imports/ui/creature/slots/LevelUpDialog.vue b/app/imports/ui/creature/slots/LevelUpDialog.vue index 7a09eb1b..4503a96e 100644 --- a/app/imports/ui/creature/slots/LevelUpDialog.vue +++ b/app/imports/ui/creature/slots/LevelUpDialog.vue @@ -192,18 +192,17 @@ import getSlotFillFilter from '/imports/api/creature/creatureProperties/methods/ import Libraries from '/imports/api/library/Libraries.js'; import LibraryNodeExpansionContent from '/imports/ui/library/LibraryNodeExpansionContent.vue'; import PropertyTags from '/imports/ui/properties/viewers/shared/PropertyTags.vue'; -import { getPropertyName } from '/imports/constants/PROPERTIES.js'; import { clone } from 'lodash'; export default { components: { - DialogBase, + DialogBase, TreeNodeView, PropertyDescription, LibraryNodeExpansionContent, PropertyTags, - }, - props:{ + }, + props: { classId: { type: String, default: undefined, @@ -217,42 +216,44 @@ export default { default: undefined, }, }, - data(){return { - selectedNodeIds: [], - searchInput: undefined, - searchValue: undefined, - showDisabled: false, - disabledNodeCount: undefined, - }}, + data() { + return { + selectedNodeIds: [], + searchInput: undefined, + searchValue: undefined, + showDisabled: false, + disabledNodeCount: undefined, + } + }, reactiveProvide: { name: 'context', include: ['creatureId'], }, computed: { - tagsSearched(){ + tagsSearched() { let or = []; let not = []; - if (this.model.slotTags && this.model.slotTags.length){ + if (this.model.slotTags && this.model.slotTags.length) { or.push(this.model.slotTags); } this.model.extraTags?.forEach(extras => { - if (extras.tags?.length){ - if(extras.operation === 'OR'){ + if (extras.tags?.length) { + if (extras.operation === 'OR') { or.push(extras.tags); - } else if (extras.operation === 'NOT'){ + } else if (extras.operation === 'NOT') { not.push(extras.tags); } } }); - return {or, not}; + return { or, not }; }, }, methods: { - loadMore(){ + loadMore() { if (this.currentLimit >= this.countAll) return; this._subs['classFillers'].setData('limit', this.currentLimit + 50); }, - openPropertyDetails(id){ + openPropertyDetails(id) { this.$store.commit('pushDialogStack', { component: 'library-node-dialog', elementId: id, @@ -261,26 +262,26 @@ export default { }, }); }, - isDisabled(node){ + isDisabled(node) { return node._disabledBySlotFillerCondition || node._disabledByAlreadyAdded || - ( - node._disabledByQuantityFilled && - !this.selectedNodeIds.includes(node._id) - ) + ( + node._disabledByQuantityFilled && + !this.selectedNodeIds.includes(node._id) + ) }, }, meteor: { $subscribe: { - 'classFillers'(){ + 'classFillers'() { return [this.classId, this.searchValue || undefined] }, }, - searchLoading(){ + searchLoading() { return !!this.searchValue && !this.$subReady.classFillers; }, - model(){ - if (this.classId){ + model() { + if (this.classId) { return CreatureProperties.findOne(this.classId); } else if (this.dummySlot) { let model = clone(this.dummySlot) @@ -294,40 +295,40 @@ export default { if (!this.creatureId) return {}; return CreatureVariables.findOne({ _creatureId: this.creatureId }) || {}; }, - currentLimit(){ + currentLimit() { return this._subs['classFillers'].data('limit') || 50; }, - countAll(){ + countAll() { return this._subs['classFillers'].data('countAll'); }, - alreadyAdded(){ + alreadyAdded() { let added = new Set(); if (!this.model.unique) return added; let ancestorId; - if (this.model.unique === 'uniqueInSlot'){ + if (this.model.unique === 'uniqueInSlot') { ancestorId = this.model._id; - } else if (this.model.unique === 'uniqueInCreature'){ + } else if (this.model.unique === 'uniqueInCreature') { ancestorId = this.creatureId; } CreatureProperties.find({ 'ancestors.id': ancestorId, - libraryNodeId: {$exists: true}, - removed: {$ne: true}, + libraryNodeId: { $exists: true }, + removed: { $ne: true }, }, { - fields: {libraryNodeId: 1}, + fields: { libraryNodeId: 1 }, }).forEach(prop => { added.add(prop.libraryNodeId); }); return added; }, - totalQuantitySelected(){ + totalQuantitySelected() { let quantitySelected = 0; LibraryNodes.find({ - _id: {$in: this.selectedNodeIds} + _id: { $in: this.selectedNodeIds } }, { - fields: {slotQuantityFilled: 1}, + fields: { slotQuantityFilled: 1 }, }).forEach(node => { - if (Number.isFinite(node.slotQuantityFilled)){ + if (Number.isFinite(node.slotQuantityFilled)) { quantitySelected += node.slotQuantityFilled; } else { quantitySelected += 1; @@ -335,30 +336,30 @@ export default { }); return quantitySelected; }, - spaceLeft(){ + spaceLeft() { if (!this.model.quantityExpected || this.model.quantityExpected.value === 0) return undefined; return this.model.spaceLeft - this.totalQuantitySelected; }, - libraryNames(){ + libraryNames() { let names = {}; Libraries.find().forEach(lib => names[lib._id] = lib.name) return names; }, - libraryNodes(){ + libraryNodes() { let filter = getSlotFillFilter({ slot: this.model }); let nodes = LibraryNodes.find(filter, { - sort: {name: 1, order: 1} + sort: { name: 1, order: 1 } }).fetch(); let disabledNodeCount = 0; // Mark classFillers whose condition isn't met or are too big to fit // the quantity to fill nodes.forEach(node => { - if (node.slotFillerCondition){ + if (node.slotFillerCondition) { try { let parseNode = parse(node.slotFillerCondition); - const {result: resultNode} = resolve('reduce', parseNode, this.variables); - if (resultNode?.parseType === 'constant'){ - if (!resultNode.value){ + const { result: resultNode } = resolve('reduce', parseNode, this.variables); + if (resultNode?.parseType === 'constant') { + if (!resultNode.value) { node._disabledBySlotFillerCondition = true; disabledNodeCount += 1; } @@ -367,7 +368,7 @@ export default { node._conditionError = toString(resultNode); disabledNodeCount += 1; } - } catch (e){ + } catch (e) { console.warn(e); let error = prettifyParseError(e); node._disabledBySlotFillerCondition = true; @@ -378,10 +379,10 @@ export default { let quantityToFill = node.type === 'slotFiller' ? node.slotQuantityFilled : 1; if ( quantityToFill > this.spaceLeft - ){ + ) { node._disabledByQuantityFilled = true; } - if (this.alreadyAdded.has(node._id)){ + if (this.alreadyAdded.has(node._id)) { node._disabledByAlreadyAdded = true; } }); @@ -393,7 +394,7 @@ export default { diff --git a/app/imports/ui/creature/slots/SlotFillDialog.vue b/app/imports/ui/creature/slots/SlotFillDialog.vue index caee497e..cbad8fb9 100644 --- a/app/imports/ui/creature/slots/SlotFillDialog.vue +++ b/app/imports/ui/creature/slots/SlotFillDialog.vue @@ -198,13 +198,13 @@ import { clone } from 'lodash'; export default { components: { - DialogBase, + DialogBase, TreeNodeView, PropertyDescription, LibraryNodeExpansionContent, PropertyTags, - }, - props:{ + }, + props: { slotId: { type: String, default: undefined, @@ -218,36 +218,38 @@ export default { default: undefined, }, }, - data(){return { - selectedNodeIds: [], - searchInput: undefined, - searchValue: undefined, - showDisabled: false, - disabledNodeCount: undefined, - }}, + data() { + return { + selectedNodeIds: [], + searchInput: undefined, + searchValue: undefined, + showDisabled: false, + disabledNodeCount: undefined, + } + }, reactiveProvide: { name: 'context', include: ['creatureId'], }, computed: { - tagsSearched(){ + tagsSearched() { let or = []; let not = []; - if (this.model.slotTags && this.model.slotTags.length){ + if (this.model.slotTags && this.model.slotTags.length) { or.push(this.model.slotTags); } this.model.extraTags?.forEach(extras => { - if (extras.tags?.length){ - if(extras.operation === 'OR'){ + if (extras.tags?.length) { + if (extras.operation === 'OR') { or.push(extras.tags); - } else if (extras.operation === 'NOT'){ + } else if (extras.operation === 'NOT') { not.push(extras.tags); } } }); - return {or, not}; + return { or, not }; }, - slotPropertyTypeName(){ + slotPropertyTypeName() { if (!this.model) return; if (!this.model.slotType) return 'Property'; let propName = getPropertyName(this.model.slotType); @@ -255,11 +257,11 @@ export default { }, }, methods: { - loadMore(){ + loadMore() { if (this.currentLimit >= this.countAll) return; this._subs['slotFillers'].setData('limit', this.currentLimit + 50); }, - openPropertyDetails(id){ + openPropertyDetails(id) { this.$store.commit('pushDialogStack', { component: 'library-node-dialog', elementId: id, @@ -268,26 +270,26 @@ export default { }, }); }, - isDisabled(node){ + isDisabled(node) { return node._disabledBySlotFillerCondition || node._disabledByAlreadyAdded || - ( - node._disabledByQuantityFilled && - !this.selectedNodeIds.includes(node._id) - ) + ( + node._disabledByQuantityFilled && + !this.selectedNodeIds.includes(node._id) + ) }, }, meteor: { $subscribe: { - 'slotFillers'(){ + 'slotFillers'() { return [this.slotId, this.searchValue || undefined] }, }, - searchLoading(){ + searchLoading() { return !!this.searchValue && !this.$subReady.slotFillers; }, - model(){ - if (this.slotId){ + model() { + if (this.slotId) { return CreatureProperties.findOne(this.slotId); } else if (this.dummySlot) { let model = clone(this.dummySlot) @@ -301,40 +303,40 @@ export default { if (!this.creatureId) return {}; return CreatureVariables.findOne({ _creatureId: this.creatureId }) || {}; }, - currentLimit(){ + currentLimit() { return this._subs['slotFillers'].data('limit') || 50; }, - countAll(){ + countAll() { return this._subs['slotFillers'].data('countAll'); }, - alreadyAdded(){ + alreadyAdded() { let added = new Set(); if (!this.model.unique) return added; let ancestorId; - if (this.model.unique === 'uniqueInSlot'){ + if (this.model.unique === 'uniqueInSlot') { ancestorId = this.model._id; - } else if (this.model.unique === 'uniqueInCreature'){ + } else if (this.model.unique === 'uniqueInCreature') { ancestorId = this.creatureId; } CreatureProperties.find({ 'ancestors.id': ancestorId, - libraryNodeId: {$exists: true}, - removed: {$ne: true}, + libraryNodeId: { $exists: true }, + removed: { $ne: true }, }, { - fields: {libraryNodeId: 1}, + fields: { libraryNodeId: 1 }, }).forEach(prop => { added.add(prop.libraryNodeId); }); return added; }, - totalQuantitySelected(){ + totalQuantitySelected() { let quantitySelected = 0; LibraryNodes.find({ - _id: {$in: this.selectedNodeIds} + _id: { $in: this.selectedNodeIds } }, { - fields: {slotQuantityFilled: 1}, + fields: { slotQuantityFilled: 1 }, }).forEach(node => { - if (Number.isFinite(node.slotQuantityFilled)){ + if (Number.isFinite(node.slotQuantityFilled)) { quantitySelected += node.slotQuantityFilled; } else { quantitySelected += 1; @@ -342,30 +344,30 @@ export default { }); return quantitySelected; }, - spaceLeft(){ + spaceLeft() { if (!this.model.quantityExpected || this.model.quantityExpected.value === 0) return undefined; return this.model.spaceLeft - this.totalQuantitySelected; }, - libraryNames(){ + libraryNames() { let names = {}; Libraries.find().forEach(lib => names[lib._id] = lib.name) return names; }, - libraryNodes(){ - let filter = getSlotFillFilter({slot: this.model}); + libraryNodes() { + let filter = getSlotFillFilter({ slot: this.model }); let nodes = LibraryNodes.find(filter, { - sort: {name: 1, order: 1} + sort: { name: 1, order: 1 } }).fetch(); let disabledNodeCount = 0; // Mark slotFillers whose condition isn't met or are too big to fit // the quantity to fill nodes.forEach(node => { - if (node.slotFillerCondition){ + if (node.slotFillerCondition) { try { let parseNode = parse(node.slotFillerCondition); - const {result: resultNode} = resolve('reduce', parseNode, this.variables); - if (resultNode?.parseType === 'constant'){ - if (!resultNode.value){ + const { result: resultNode } = resolve('reduce', parseNode, this.variables); + if (resultNode?.parseType === 'constant') { + if (!resultNode.value) { node._disabledBySlotFillerCondition = true; disabledNodeCount += 1; } @@ -374,7 +376,7 @@ export default { node._conditionError = toString(resultNode); disabledNodeCount += 1; } - } catch (e){ + } catch (e) { console.warn(e); let error = prettifyParseError(e); node._disabledBySlotFillerCondition = true; @@ -385,10 +387,10 @@ export default { let quantityToFill = node.type === 'slotFiller' ? node.slotQuantityFilled : 1; if ( quantityToFill > this.spaceLeft - ){ + ) { node._disabledByQuantityFilled = true; } - if (this.alreadyAdded.has(node._id)){ + if (this.alreadyAdded.has(node._id)) { node._disabledByAlreadyAdded = true; } }); @@ -400,7 +402,7 @@ export default { diff --git a/app/imports/ui/dialogStack/DeleteConfirmationDialog.vue b/app/imports/ui/dialogStack/DeleteConfirmationDialog.vue index d7f90460..c8b76735 100644 --- a/app/imports/ui/dialogStack/DeleteConfirmationDialog.vue +++ b/app/imports/ui/dialogStack/DeleteConfirmationDialog.vue @@ -4,7 +4,10 @@ Delete {{ typeName }}
- + This can't be undone

@@ -12,9 +15,9 @@

diff --git a/app/imports/ui/dialogStack/DialogBase.vue b/app/imports/ui/dialogStack/DialogBase.vue index 14a1f1cf..4fcdd912 100644 --- a/app/imports/ui/dialogStack/DialogBase.vue +++ b/app/imports/ui/dialogStack/DialogBase.vue @@ -50,63 +50,69 @@ diff --git a/app/imports/ui/dialogStack/HelpDialog.vue b/app/imports/ui/dialogStack/HelpDialog.vue index 158bc71e..9fe700b2 100644 --- a/app/imports/ui/dialogStack/HelpDialog.vue +++ b/app/imports/ui/dialogStack/HelpDialog.vue @@ -43,16 +43,16 @@ import MarkdownText from '/imports/ui/components/MarkdownText.vue'; import Docs from '/imports/api/docs/Docs.js'; export default { - components: { + components: { DialogBase, MarkdownText, - }, - props: { + }, + props: { path: { type: String, required: true, } - }, + }, computed: { prop() { return propsByDocsPath.get(this.path); @@ -63,7 +63,7 @@ export default { } else { const titleCase = this.path.replace( /(\w*)(\W+)/g, - function(txt, word) { + function (txt, word) { return word.charAt(0).toUpperCase() + word.substr(1).toLowerCase() + ' '; } ); @@ -73,7 +73,7 @@ export default { }, meteor: { $subscribe: { - 'docs'(){ + 'docs'() { return [this.path]; }, }, @@ -104,4 +104,5 @@ export default { diff --git a/app/imports/ui/dialogStack/mockElement.js b/app/imports/ui/dialogStack/mockElement.js index de843514..e3f19654 100644 --- a/app/imports/ui/dialogStack/mockElement.js +++ b/app/imports/ui/dialogStack/mockElement.js @@ -2,7 +2,7 @@ import { parse, stringify } from 'css-box-shadow'; // Only supports border radius defined like "20px" or "100%" const transformedRadius = (radiusString, deltaWidth, deltaHeight) => { - if (/^\d+\.?\d*px$/.test(radiusString)){ + if (/^\d+\.?\d*px$/.test(radiusString)) { //The radius is defined in pixel units, so get the radius as a number const rad = +radiusString.match(/\d+\.?\d*/)[0]; // Set the x and y radius of the "to" element, compensating for scale @@ -15,7 +15,7 @@ const transformedRadius = (radiusString, deltaWidth, deltaHeight) => { const transformedBoxShadow = (shadowString, deltaWidth, deltaHeight) => { if (shadowString === 'none') return shadowString; - if (shadowString[0] === 'r'){ + if (shadowString[0] === 'r') { let strings = shadowString.match(/rgba\([^)]+\)[^,]+/g); strings = strings.map(string => { // Move color to end @@ -35,24 +35,24 @@ const transformedBoxShadow = (shadowString, deltaWidth, deltaHeight) => { return stringify(shadows); } -export default function mockElement({source, target, offset = {x: 0, y: 0}}){ - if (!source || !target) throw `Can't mock without ${source ? 'target' : 'source'}` ; +export default function mockElement({ source, target, offset = { x: 0, y: 0 } }) { + if (!source || !target) throw `Can't mock without ${source ? 'target' : 'source'}`; let sourceRect = source.getBoundingClientRect(); - let targetRect = target.getBoundingClientRect(); + let targetRect = target.getBoundingClientRect(); - // Get how must the target change to become the source - const deltaWidth = sourceRect.width / targetRect.width; - const deltaHeight = sourceRect.height / targetRect.height; - const deltaLeft = sourceRect.left - targetRect.left + offset.x; - const deltaTop = sourceRect.top - targetRect.top + offset.y; - // Mock the source - target.style.transform = `translate(${deltaLeft}px, ${deltaTop}px) ` + + // Get how must the target change to become the source + const deltaWidth = sourceRect.width / targetRect.width; + const deltaHeight = sourceRect.height / targetRect.height; + const deltaLeft = sourceRect.left - targetRect.left + offset.x; + const deltaTop = sourceRect.top - targetRect.top + offset.y; + // Mock the source + target.style.transform = `translate(${deltaLeft}px, ${deltaTop}px) ` + `scale(${deltaWidth}, ${deltaHeight})`; - // Mock the background color unless it's completely transparent - let backgroundColor = getComputedStyle(source).backgroundColor - if (backgroundColor !== 'rgba(0, 0, 0, 0)'){ - target.style.backgroundColor = backgroundColor; - } + // Mock the background color unless it's completely transparent + let backgroundColor = getComputedStyle(source).backgroundColor + if (backgroundColor !== 'rgba(0, 0, 0, 0)') { + target.style.backgroundColor = backgroundColor; + } // Edge might not combine all border radii into a single value, // So we just sample the top left one if we need to let oldRadius = getComputedStyle(source).borderRadius || diff --git a/app/imports/ui/files/ArchiveFileCard.vue b/app/imports/ui/files/ArchiveFileCard.vue index cab9edde..d8ec1f25 100644 --- a/app/imports/ui/files/ArchiveFileCard.vue +++ b/app/imports/ui/files/ArchiveFileCard.vue @@ -44,17 +44,19 @@ export default { required: true, }, }, - data(){return { - restoreLoading: false, - removeLoading: false, - }}, - meteor: { - characterSlots(){ + data() { + return { + restoreLoading: false, + removeLoading: false, + } + }, + meteor: { + characterSlots() { return characterSlotsRemaining(Meteor.userId()); }, - }, + }, methods: { - restore(){ + restore() { this.restoreLoading = true; restoreCreatureFromFile.call({ fileId: this.model._id, @@ -62,26 +64,26 @@ export default { this.restoreLoading = false; if (!error) return; console.error(error); - snackbar({text: error.reason}); + snackbar({ text: error.reason }); + }); + }, + removeArchiveCharacter() { + let that = this; + this.$store.commit('pushDialogStack', { + component: 'delete-confirmation-dialog', + elementId: `${that.model._id}-archive-card`, + data: { + name: this.model.meta.creatureName, + typeName: 'Character Archive' + }, + callback(confirmation) { + if (!confirmation) return; + removeArchiveCreature.call({ fileId: that.model._id }, (error) => { + if (error) console.error(error); + }); + } }); }, - removeArchiveCharacter(){ - let that = this; - this.$store.commit('pushDialogStack', { - component: 'delete-confirmation-dialog', - elementId: `${that.model._id}-archive-card`, - data: { - name: this.model.meta.creatureName, - typeName: 'Character Archive' - }, - callback(confirmation){ - if(!confirmation) return; - removeArchiveCreature.call({fileId: that.model._id}, (error) => { - if (error) console.error(error); - }); - } - }); - }, }, } diff --git a/app/imports/ui/files/UserImageCard.vue b/app/imports/ui/files/UserImageCard.vue index e70141a6..85c5d155 100644 --- a/app/imports/ui/files/UserImageCard.vue +++ b/app/imports/ui/files/UserImageCard.vue @@ -34,7 +34,6 @@ diff --git a/app/imports/ui/layouts/AppLayout.vue b/app/imports/ui/layouts/AppLayout.vue index 8d958e86..99469969 100644 --- a/app/imports/ui/layouts/AppLayout.vue +++ b/app/imports/ui/layouts/AppLayout.vue @@ -6,9 +6,7 @@ > - + - +
{{ $store.state.pageTitle }}
- +
- +
- +
- + - + diff --git a/app/imports/ui/library/LibraryCollectionEditDialog.vue b/app/imports/ui/library/LibraryCollectionEditDialog.vue index 8cf2e70c..cccce61a 100644 --- a/app/imports/ui/library/LibraryCollectionEditDialog.vue +++ b/app/imports/ui/library/LibraryCollectionEditDialog.vue @@ -63,62 +63,62 @@ import { snackbar } from '/imports/ui/components/snackbars/SnackbarQueue.js'; import Libraries from '/imports/api/library/Libraries.js'; export default { - components: { - DialogBase, - }, - props: { - _id: String, - }, - methods: { - updateLibraryCollection(update, ack){ - updateLibraryCollection.call({_id: this._id, update}, (error) =>{ - ack(error && error.reason || error); - }); + components: { + DialogBase, + }, + props: { + _id: String, + }, + methods: { + updateLibraryCollection(update, ack) { + updateLibraryCollection.call({ _id: this._id, update }, (error) => { + ack(error && error.reason || error); + }); }, - remove(){ - let that = this; - this.$store.commit('pushDialogStack', { - component: 'delete-confirmation-dialog', - elementId: 'delete-library-button', - data: { - name: this.model.name, - typeName: 'Collection' - }, - callback(confirmation){ - if(!confirmation) return; - removeLibraryCollection.call({_id: that._id}, (error) => { + remove() { + let that = this; + this.$store.commit('pushDialogStack', { + component: 'delete-confirmation-dialog', + elementId: 'delete-library-button', + data: { + name: this.model.name, + typeName: 'Collection' + }, + callback(confirmation) { + if (!confirmation) return; + removeLibraryCollection.call({ _id: that._id }, (error) => { if (error) { console.error(error); snackbar({ text: error.reason, }); - } else { + } else { that.$router.push({ name: 'library', replace: true }); that.$store.dispatch('popDialogStack'); - } - }); - } - }); - }, - share(){ - this.$store.commit('pushDialogStack', { - component: 'share-dialog', - elementId: 'share-library-button', - data: { - docRef: { + } + }); + } + }); + }, + share() { + this.$store.commit('pushDialogStack', { + component: 'share-dialog', + elementId: 'share-library-button', + data: { + docRef: { id: this._id, collection: 'libraryCollections', } - }, - }); - }, - }, - meteor: { - '$subscribe':{ + }, + }); + }, + }, + meteor: { + '$subscribe': { libraries: [], }, - model(){ - return LibraryCollections.findOne(this._id); + model() { + return LibraryCollections.findOne(this._id); }, libraryOptions() { const userId = Meteor.userId(); @@ -131,7 +131,7 @@ export default { { public: true }, ] }, - {sort: {name: 1}} + { sort: { name: 1 } } ).map(library => { return { text: library.name, @@ -139,9 +139,10 @@ export default { }; }); }, - } + } } diff --git a/app/imports/ui/library/LibraryCollectionToolbar.vue b/app/imports/ui/library/LibraryCollectionToolbar.vue index 4147836e..0a128b90 100644 --- a/app/imports/ui/library/LibraryCollectionToolbar.vue +++ b/app/imports/ui/library/LibraryCollectionToolbar.vue @@ -43,24 +43,26 @@ import { assertDocEditPermission } from '/imports/api/sharing/sharingPermissions import { mapMutations } from 'vuex'; export default { - data(){ return { - loading: false, - }}, + data() { + return { + loading: false, + } + }, meteor: { - libraryCollection(){ + libraryCollection() { return LibraryCollections.findOne(this.$route.params.id); }, - subscribed(){ + subscribed() { const libraryCollectionId = this.$route.params.id; const user = Meteor.user(); return user?.subscribedLibraryCollections?.includes(libraryCollectionId); }, - showSubscribeButton(){ + showSubscribeButton() { let user = Meteor.user(); let libraryCollection = this.libraryCollection; if (!user || !libraryCollection) return; let userId = user._id; - if (user.subscribedLibraryCollections?.includes(libraryCollection._id)){ + if (user.subscribedLibraryCollections?.includes(libraryCollection._id)) { return true } else if ( libraryCollection.readers.includes(userId) || @@ -72,7 +74,7 @@ export default { return true; } }, - canEdit(){ + canEdit() { try { assertDocEditPermission(this.libraryCollection, Meteor.userId()); return true @@ -85,7 +87,7 @@ export default { ...mapMutations([ 'toggleDrawer', ]), - subscribe(value){ + subscribe(value) { this.loading = true; Meteor.users.subscribeToLibraryCollection.call({ libraryCollectionId: this.$route.params.id, @@ -94,16 +96,17 @@ export default { this.loading = false; }); }, - editLibraryCollection(){ - this.$store.commit('pushDialogStack', { - component: 'library-collection-edit-dialog', - elementId: 'library-collection-edit-button', - data: {_id: this.$route.params.id}, - }); - }, + editLibraryCollection() { + this.$store.commit('pushDialogStack', { + component: 'library-collection-edit-dialog', + elementId: 'library-collection-edit-button', + data: { _id: this.$route.params.id }, + }); + }, }, } diff --git a/app/imports/ui/library/LibraryContentsContainer.vue b/app/imports/ui/library/LibraryContentsContainer.vue index f30e30fb..1e70fa07 100644 --- a/app/imports/ui/library/LibraryContentsContainer.vue +++ b/app/imports/ui/library/LibraryContentsContainer.vue @@ -1,7 +1,5 @@ - + + diff --git a/app/imports/ui/library/SingleLibraryToolbar.vue b/app/imports/ui/library/SingleLibraryToolbar.vue index fc953903..c3404d8f 100644 --- a/app/imports/ui/library/SingleLibraryToolbar.vue +++ b/app/imports/ui/library/SingleLibraryToolbar.vue @@ -43,24 +43,26 @@ import { assertDocEditPermission } from '/imports/api/sharing/sharingPermissions import { mapMutations } from 'vuex'; export default { - data(){ return { - loading: false, - }}, + data() { + return { + loading: false, + } + }, meteor: { - library(){ + library() { return Libraries.findOne(this.$route.params.id); }, - subscribed(){ + subscribed() { let libraryId = this.$route.params.id; let user = Meteor.user(); return user?.subscribedLibraries?.includes(libraryId); }, - showSubscribeButton(){ + showSubscribeButton() { let user = Meteor.user(); let library = this.library; if (!user || !library) return; let userId = user._id; - if (user.subscribedLibraries.includes(library._id)){ + if (user.subscribedLibraries.includes(library._id)) { return true } else if ( library.readers.includes(userId) || @@ -72,7 +74,7 @@ export default { return true; } }, - canEdit(){ + canEdit() { try { assertDocEditPermission(this.library, Meteor.userId()); return true @@ -85,7 +87,7 @@ export default { ...mapMutations([ 'toggleDrawer', ]), - subscribe(value){ + subscribe(value) { this.loading = true; Meteor.users.subscribeToLibrary.call({ libraryId: this.$route.params.id, @@ -94,16 +96,17 @@ export default { this.loading = false; }); }, - editLibrary(){ - this.$store.commit('pushDialogStack', { - component: 'library-edit-dialog', - elementId: 'library-edit-button', - data: {_id: this.$route.params.id}, - }); - }, + editLibrary() { + this.$store.commit('pushDialogStack', { + component: 'library-edit-dialog', + elementId: 'library-edit-button', + data: { _id: this.$route.params.id }, + }); + }, }, } diff --git a/app/imports/ui/pages/CharacterSheetPage.vue b/app/imports/ui/pages/CharacterSheetPage.vue index c21908db..a2346e36 100644 --- a/app/imports/ui/pages/CharacterSheetPage.vue +++ b/app/imports/ui/pages/CharacterSheetPage.vue @@ -8,8 +8,8 @@ diff --git a/app/imports/ui/pages/Documentation.vue b/app/imports/ui/pages/Documentation.vue index 8a0acb10..c94fe41f 100644 --- a/app/imports/ui/pages/Documentation.vue +++ b/app/imports/ui/pages/Documentation.vue @@ -37,9 +37,9 @@ import Docs from '/imports/api/docs/Docs.js'; import { propsByDocsPath } from '/imports/constants/PROPERTIES.js'; export default { - components: { + components: { MarkdownText, - }, + }, data() { return { action: undefined, @@ -54,21 +54,21 @@ export default { }, title() { if (this.prop) { - return this.prop.name + ' Docs'; - } else { - const titleCase = this.path.replace( - /(\w*)(\W+)/g, - function(txt, word) { - return word.charAt(0).toUpperCase() + word.substr(1).toLowerCase() + ' '; - } - ); - return titleCase || 'DiceCloud Docs'; - } + return this.prop.name + ' Docs'; + } else { + const titleCase = this.path.replace( + /(\w*)(\W+)/g, + function (txt, word) { + return word.charAt(0).toUpperCase() + word.substr(1).toLowerCase() + ' '; + } + ); + return titleCase || 'DiceCloud Docs'; + } } }, meteor: { $subscribe: { - 'docs'(){ + 'docs'() { return [this.path]; }, }, diff --git a/app/imports/ui/pages/Home.vue b/app/imports/ui/pages/Home.vue index 171ade01..72642172 100644 --- a/app/imports/ui/pages/Home.vue +++ b/app/imports/ui/pages/Home.vue @@ -132,17 +132,17 @@ diff --git a/app/imports/ui/pages/SignIn.vue b/app/imports/ui/pages/SignIn.vue index 87f83356..a1a0ba2e 100644 --- a/app/imports/ui/pages/SignIn.vue +++ b/app/imports/ui/pages/SignIn.vue @@ -91,53 +91,53 @@ diff --git a/app/imports/ui/properties/components/actions/ActionCard.vue b/app/imports/ui/properties/components/actions/ActionCard.vue index 50f22c18..cf204d71 100644 --- a/app/imports/ui/properties/components/actions/ActionCard.vue +++ b/app/imports/ui/properties/components/actions/ActionCard.vue @@ -38,9 +38,7 @@ :disabled="model.insufficientResources || !context.editPermission" @click.stop="doAction" > - +
-
+
{{ model.name || propertyName }}
@@ -89,9 +85,7 @@ /> 3; }, - propertyName(){ + propertyName() { return getPropertyName(this.model.type); }, cardClasses() { @@ -173,12 +169,12 @@ export default { actionTypeIcon() { return `$vuetify.icons.${this.model.actionType}`; }, - }, + }, methods: { - click(e){ - this.$emit('click', e); - }, - doAction({advantage}){ + click(e) { + this.$emit('click', e); + }, + doAction({ advantage }) { this.doActionLoading = true; this.shwing(); doAction.call({ @@ -188,13 +184,13 @@ export default { } }, error => { this.doActionLoading = false; - if (error){ + if (error) { console.error(error); - snackbar({text: error.reason}); + snackbar({ text: error.reason }); } }); }, - shwing(){ + shwing() { this.activated = true; setTimeout(() => { this.activated = undefined; @@ -209,9 +205,11 @@ export default { transition: box-shadow .4s cubic-bezier(0.25, 0.8, 0.25, 1), transform 0.075s ease; } + .action-card.active { transform: scale(0.92); } + .action-title { font-size: 16px; font-weight: 400; @@ -222,9 +220,10 @@ export default { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - transition: .3s cubic-bezier(.25,.8,.5,1); + transition: .3s cubic-bezier(.25, .8, .5, 1); width: 100%; } + .action-sub-title { color: #9e9e9e; flex-grow: 0; @@ -236,15 +235,19 @@ export default { text-overflow: ellipsis; width: 100%; } + .action-child { height: 32px; } + .theme--light.muted-text { - color: rgba(0,0,0,.3) !important; + color: rgba(0, 0, 0, .3) !important; } + .theme--dark.muted-text { - color: hsla(0,0%,100%,.3) !important; + color: hsla(0, 0%, 100%, .3) !important; } + .action-card { transition: transform 0.15s cubic; } @@ -252,12 +255,14 @@ export default { diff --git a/app/imports/ui/properties/components/attributes/AbilityListTile.vue b/app/imports/ui/properties/components/attributes/AbilityListTile.vue index c4d748da..46d36bb8 100644 --- a/app/imports/ui/properties/components/attributes/AbilityListTile.vue +++ b/app/imports/ui/properties/components/attributes/AbilityListTile.vue @@ -55,7 +55,7 @@ import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import RollPopup from '/imports/ui/components/RollPopup.vue'; import doCheck from '/imports/api/engine/actions/doCheck.js'; -import {snackbar} from '/imports/ui/components/snackbars/SnackbarQueue.js'; +import { snackbar } from '/imports/ui/components/snackbars/SnackbarQueue.js'; export default { components: { @@ -66,23 +66,25 @@ export default { default: {}, }, }, - props: { - model: {type: Object, required: true}, - }, - data(){return { - checkLoading: false, - }}, - computed: { - hasClickListener(){ + props: { + model: { type: Object, required: true }, + }, + data() { + return { + checkLoading: false, + } + }, + computed: { + hasClickListener() { return this.$listeners && this.$listeners.click - }, - }, - methods: { - numberToSignedString, - click(e){ - this.$emit('click', e); - }, - check({advantage}){ + }, + }, + methods: { + numberToSignedString, + click(e) { + this.$emit('click', e); + }, + check({ advantage }) { this.checkLoading = true; doCheck.call({ propId: this.model._id, @@ -91,15 +93,15 @@ export default { }, }, error => { this.checkLoading = false; - if (error){ + if (error) { console.error(error); - snackbar({text: error.reason}); + snackbar({ text: error.reason }); } }); }, - }, + }, meteor: { - swapScoresAndMods(){ + swapScoresAndMods() { let user = Meteor.user(); return user && user.preferences && @@ -110,26 +112,32 @@ export default { diff --git a/app/imports/ui/properties/components/attributes/HealthBar.vue b/app/imports/ui/properties/components/attributes/HealthBar.vue index ae9b3bce..da4bbb7d 100644 --- a/app/imports/ui/properties/components/attributes/HealthBar.vue +++ b/app/imports/ui/properties/components/attributes/HealthBar.vue @@ -104,9 +104,18 @@ export default { }, }, props: { - value: Number, - maxValue: Number, - name: String, + value: { + type: Number, + default: undefined, + }, + maxValue: { + type: Number, + default: undefined, + }, + name: { + type: String, + default: undefined, + }, color: { type: String, default() { @@ -139,22 +148,22 @@ export default { barColor() { const fraction = this.value / this.maxValue; if (!Number.isFinite(fraction)) return this.color; - if (fraction > 0.5){ + if (fraction > 0.5) { return this.color; } else if (this.midColor && this.lowColor) { return chroma.mix(this.lowColor, this.midColor, fraction * 2).hex(); - } else if (this.midColor){ + } else if (this.midColor) { return this.midColor; } return this.color; }, - barBackgroundColor(){ + barBackgroundColor() { return chroma(this.barColor) - .darken(1.5) - .desaturate(1.5) - .hex(); + .darken(1.5) + .desaturate(1.5) + .hex(); }, - isTextLight(){ + isTextLight() { return isDarkColor(this.barBackgroundColor); /* Change color at the halfway mark const fraction = this.value / this.maxValue; @@ -173,7 +182,7 @@ export default { cancelEdit() { this.editing = false; }, - changeIncrementMenu(e){ + changeIncrementMenu(e) { this.$emit('change', e); this.editing = false; } @@ -193,70 +202,85 @@ export default { diff --git a/app/imports/ui/properties/components/attributes/HealthBarCard.vue b/app/imports/ui/properties/components/attributes/HealthBarCard.vue index f05c7978..c3409ee0 100644 --- a/app/imports/ui/properties/components/attributes/HealthBarCard.vue +++ b/app/imports/ui/properties/components/attributes/HealthBarCard.vue @@ -17,17 +17,17 @@ diff --git a/app/imports/ui/properties/components/attributes/HealthBarCardContainer.vue b/app/imports/ui/properties/components/attributes/HealthBarCardContainer.vue index 9b8440e7..639beee0 100644 --- a/app/imports/ui/properties/components/attributes/HealthBarCardContainer.vue +++ b/app/imports/ui/properties/components/attributes/HealthBarCardContainer.vue @@ -12,60 +12,60 @@ diff --git a/app/imports/ui/properties/components/attributes/HitDiceListTile.vue b/app/imports/ui/properties/components/attributes/HitDiceListTile.vue index e26f1abd..7cfff667 100644 --- a/app/imports/ui/properties/components/attributes/HitDiceListTile.vue +++ b/app/imports/ui/properties/components/attributes/HitDiceListTile.vue @@ -31,9 +31,7 @@ - +
{{ model.value }}
@@ -63,60 +61,71 @@ export default { inject: { context: { default: {} } }, - props: { + props: { model: { type: Object, required: true, } - }, - data(){ return{ - hover: false, - }}, + }, + data() { + return { + hover: false, + } + }, computed: { - signedConMod(){ + signedConMod() { return numberToSignedString(this.model.constitutionMod); }, }, - methods: { - click(e){ - this.$emit('click', e); - }, - increment(value){ - this.$emit('change', {type: 'increment', value}) - }, - }, + methods: { + click(e) { + this.$emit('click', e); + }, + increment(value) { + this.$emit('change', { type: 'increment', value }) + }, + }, }; diff --git a/app/imports/ui/properties/components/attributes/ResourceCard.vue b/app/imports/ui/properties/components/attributes/ResourceCard.vue index 44390756..c5759892 100644 --- a/app/imports/ui/properties/components/attributes/ResourceCard.vue +++ b/app/imports/ui/properties/components/attributes/ResourceCard.vue @@ -22,9 +22,7 @@ mdi-chevron-down
-
+
{{ model.value }}
@@ -53,55 +51,64 @@ diff --git a/app/imports/ui/properties/components/attributes/SpellSlotListTile.vue b/app/imports/ui/properties/components/attributes/SpellSlotListTile.vue index 02afc030..584fc765 100644 --- a/app/imports/ui/properties/components/attributes/SpellSlotListTile.vue +++ b/app/imports/ui/properties/components/attributes/SpellSlotListTile.vue @@ -7,9 +7,7 @@ v-on="hasClickListener ? {click} : {}" > - +
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; export default { - props: { - model: { + props: { + model: { type: Object, required: true, }, dark: Boolean, hideCastButton: Boolean, disabled: Boolean, - }, - computed: { - hasClickListener(){ + }, + computed: { + hasClickListener() { return this.$listeners && !!this.$listeners.click; }, - }, - methods: { - signed: numberToSignedString, - click(e){ - this.$emit('click', e); - }, - }, + }, + methods: { + signed: numberToSignedString, + click(e) { + this.$emit('click', e); + }, + }, }; diff --git a/app/imports/ui/properties/components/inventory/ContainerCard.vue b/app/imports/ui/properties/components/inventory/ContainerCard.vue index 6d862b60..0843dcfd 100644 --- a/app/imports/ui/properties/components/inventory/ContainerCard.vue +++ b/app/imports/ui/properties/components/inventory/ContainerCard.vue @@ -30,9 +30,7 @@ > $vuetify.icons.two_coins - + @@ -52,57 +50,57 @@ import CoinValue from '/imports/ui/components/CoinValue.vue'; import stripFloatingPointOddities from '/imports/api/engine/computation/utility/stripFloatingPointOddities.js'; export default { - components: { - ToolbarCard, + components: { + ToolbarCard, ItemList, CoinValue, - }, - props: { - model: { + }, + props: { + model: { type: Object, required: true, }, - }, + }, computed: { - weight(){ + weight() { const contentWeight = this.model.contentsWeightless ? 0 : this.model.contentsWeight || 0; const ownWeight = this.model.weight || 0; return stripFloatingPointOddities(contentWeight + ownWeight); }, - value(){ + value() { const contentValue = this.model.contentsValue || 0; const ownValue = this.model.value || 0; return contentValue + ownValue; } }, - methods: { - clickContainer(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `${_id}`, - data: {_id}, - }); - }, - clickProperty(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `tree-node-${_id}`, - data: {_id}, - }); - }, - }, + methods: { + clickContainer(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: `${_id}`, + data: { _id }, + }); + }, + clickProperty(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: `tree-node-${_id}`, + data: { _id }, + }); + }, + }, meteor: { - items(){ + items() { return CreatureProperties.find({ 'parent.id': this.model._id, - type: {$in: ['item', 'container']}, - removed: {$ne: true}, - equipped: {$ne: true}, - deactivatedByAncestor: {$ne: true}, + type: { $in: ['item', 'container'] }, + removed: { $ne: true }, + equipped: { $ne: true }, + deactivatedByAncestor: { $ne: true }, }, { - sort: {order: 1}, + sort: { order: 1 }, }); }, } @@ -110,4 +108,5 @@ export default { diff --git a/app/imports/ui/properties/components/inventory/ItemList.vue b/app/imports/ui/properties/components/inventory/ItemList.vue index 6696ee12..28a07995 100644 --- a/app/imports/ui/properties/components/inventory/ItemList.vue +++ b/app/imports/ui/properties/components/inventory/ItemList.vue @@ -52,40 +52,42 @@ export default { preparingSpells: Boolean, equipment: Boolean, }, - data(){ return { - dataItems: [], - }}, + data() { + return { + dataItems: [], + } + }, computed: { - levels(){ + levels() { let levels = new Set(); this.items.forEach(item => levels.add(item.level)); return levels; }, }, watch: { - items(value){ + items(value) { this.dataItems = value; } }, - mounted(){ + mounted() { this.dataItems = this.items; }, methods: { - clickProperty(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: _id, - data: {_id}, - }); - }, - change({added, moved}){ + clickProperty(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: _id, + data: { _id }, + }); + }, + change({ added, moved }) { let event = added || moved; - if (event){ + if (event) { // If this item is now adjacent to another, set the order accordingly let order; let before = this.dataItems[event.newIndex - 1]; let after = this.dataItems[event.newIndex + 1]; - if (before && before._id){ + if (before && before._id) { order = before.order + 0.5; } else if (after && after._id) { order = after.order - 0.5; @@ -101,7 +103,7 @@ export default { parentRef: this.parentRef, order, }); - if (doc.type === 'item' && doc.equipped != this.equipment){ + if (doc.type === 'item' && doc.equipped != this.equipment) { updateCreatureProperty.call({ _id: doc._id, path: ['equipped'], @@ -111,6 +113,6 @@ export default { } setTimeout(() => this.dataItems = this.items, 0); }, - } + } } diff --git a/app/imports/ui/properties/components/inventory/ItemListTile.vue b/app/imports/ui/properties/components/inventory/ItemListTile.vue index d6e64249..5dfa1b8e 100644 --- a/app/imports/ui/properties/components/inventory/ItemListTile.vue +++ b/app/imports/ui/properties/components/inventory/ItemListTile.vue @@ -49,10 +49,10 @@ import treeNodeViewMixin from '/imports/ui/properties/treeNodeViews/treeNodeView import PROPERTIES from '/imports/constants/PROPERTIES.js'; import adjustQuantity from '/imports/api/creature/creatureProperties/methods/adjustQuantity.js'; import IncrementButton from '/imports/ui/components/IncrementButton.vue'; -import {snackbar} from '/imports/ui/components/snackbars/SnackbarQueue.js'; +import { snackbar } from '/imports/ui/components/snackbars/SnackbarQueue.js'; export default { - components:{ + components: { IncrementButton, }, mixins: [treeNodeViewMixin], @@ -62,20 +62,22 @@ export default { props: { preparingSpells: Boolean, }, - data(){return { - incrementLoading: false, - }}, + data() { + return { + incrementLoading: false, + } + }, computed: { - hasClickListener(){ + hasClickListener() { return this.$listeners && !!this.$listeners.click; }, - title(){ + title() { let model = this.model; if (!model) return; - if (model.quantity !== 1){ - if (model.plural){ + if (model.quantity !== 1) { + if (model.plural) { return `${model.quantity} ${model.plural}`; - } else if (model.name){ + } else if (model.name) { return `${model.quantity} ${model.name}`; } } else if (model.name) { @@ -86,10 +88,10 @@ export default { } }, methods: { - click(e){ - this.$emit('click', e); - }, - changeQuantity({type, value}) { + click(e) { + this.$emit('click', e); + }, + changeQuantity({ type, value }) { this.incrementLoading = true; adjustQuantity.call({ _id: this.model._id, @@ -97,8 +99,8 @@ export default { value: value }, error => { this.incrementLoading = false; - if (error){ - snackbar({text: error.reason}); + if (error) { + snackbar({ text: error.reason }); console.error(error); } }); @@ -111,6 +113,7 @@ export default { .item-avatar { min-width: 32px; } + .item { background-color: inherit; } diff --git a/app/imports/ui/properties/components/persona/NoteCard.vue b/app/imports/ui/properties/components/persona/NoteCard.vue index f3be2a0e..d07afa1e 100644 --- a/app/imports/ui/properties/components/persona/NoteCard.vue +++ b/app/imports/ui/properties/components/persona/NoteCard.vue @@ -31,10 +31,10 @@ import isDarkColor from '/imports/ui/utility/isDarkColor.js'; import CardHighlight from '/imports/ui/components/CardHighlight.vue'; export default { - components: { - PropertyDescription, + components: { + PropertyDescription, CardHighlight, - }, + }, inject: { theme: { default: { @@ -42,31 +42,34 @@ export default { }, }, }, - props: { - model: { + props: { + model: { type: Object, required: true, }, - }, - data(){ return{ - hover: false, - }}, + }, + data() { + return { + hover: false, + } + }, computed: { - isDark(){ + isDark() { return isDarkColor(this.model.color); }, }, - methods: { - clickProperty(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `${_id}`, - data: {_id}, - }); - }, - }, + methods: { + clickProperty(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: `${_id}`, + data: { _id }, + }); + }, + }, }; diff --git a/app/imports/ui/properties/components/skills/SkillListTile.vue b/app/imports/ui/properties/components/skills/SkillListTile.vue index e24ece45..bbcb773e 100644 --- a/app/imports/ui/properties/components/skills/SkillListTile.vue +++ b/app/imports/ui/properties/components/skills/SkillListTile.vue @@ -62,7 +62,7 @@ import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import ProficiencyIcon from '/imports/ui/properties/shared/ProficiencyIcon.vue'; import RollPopup from '/imports/ui/components/RollPopup.vue'; import doCheck from '/imports/api/engine/actions/doCheck.js'; -import {snackbar} from '/imports/ui/components/snackbars/SnackbarQueue.js'; +import { snackbar } from '/imports/ui/components/snackbars/SnackbarQueue.js'; export default { components: { @@ -74,37 +74,39 @@ export default { default: {}, }, }, - props: { + props: { model: { type: Object, required: true, }, hideModifier: Boolean, - }, - data(){return { - checkLoading: false, - }}, - computed: { - displayedModifier(){ - let mod = this.model.value; - if (this.model.fail){ - return 'fail'; - } else { - return numberToSignedString(mod); - } - }, - hasClickListener(){ + }, + data() { + return { + checkLoading: false, + } + }, + computed: { + displayedModifier() { + let mod = this.model.value; + if (this.model.fail) { + return 'fail'; + } else { + return numberToSignedString(mod); + } + }, + hasClickListener() { return this.$listeners && this.$listeners.click - }, - passiveScore(){ + }, + passiveScore() { return 10 + this.model.value + this.model.passiveBonus; } - }, - methods: { - click(e){ - this.$emit('click', e); - }, - check({advantage}){ + }, + methods: { + click(e) { + this.$emit('click', e); + }, + check({ advantage }) { this.checkLoading = true; doCheck.call({ propId: this.model._id, @@ -113,24 +115,26 @@ export default { }, }, error => { this.checkLoading = false; - if (error){ + if (error) { console.error(error); - snackbar({text: error.reason}); + snackbar({ text: error.reason }); } }); }, - } + } } diff --git a/app/imports/ui/properties/components/spells/CastSpellWithSlotDialog.vue b/app/imports/ui/properties/components/spells/CastSpellWithSlotDialog.vue index c3ec9a92..cf9cf288 100644 --- a/app/imports/ui/properties/components/spells/CastSpellWithSlotDialog.vue +++ b/app/imports/ui/properties/components/spells/CastSpellWithSlotDialog.vue @@ -184,10 +184,10 @@ import { find } from 'lodash'; const slotFilter = { type: 'attribute', attributeType: 'spellSlot', - removed: {$ne: true}, - inactive: {$ne: true}, - overridden: {$ne: true}, - 'spellSlotLevel.value': {$gte: 1}, + removed: { $ne: true }, + inactive: { $ne: true }, + overridden: { $ne: true }, + 'spellSlotLevel.value': { $gte: 1 }, }; export default { @@ -212,36 +212,38 @@ export default { default: undefined, }, }, - data(){ return { - searchString: undefined, - selectedSlotId: this.slotId, - selectedSpellId: this.spellId, - selectedSlot: undefined, - selectedSpell: undefined, - searchValue: undefined, - searchError: undefined, - filterMenuOpen: false, - booleanFilters: { - verbal: {name: 'Verbal', enabled: false, value: false}, - somatic: {name: 'Somatic', enabled: false, value: false}, - material: {name: 'Material', enabled: false, value: false}, - concentration: {name: 'Concentration', enabled: false, value: false}, - ritual: {name: 'Ritual', enabled: false, value: false}, - }, - }}, + data() { + return { + searchString: undefined, + selectedSlotId: this.slotId, + selectedSpellId: this.spellId, + selectedSlot: undefined, + selectedSpell: undefined, + searchValue: undefined, + searchError: undefined, + filterMenuOpen: false, + booleanFilters: { + verbal: { name: 'Verbal', enabled: false, value: false }, + somatic: { name: 'Somatic', enabled: false, value: false }, + material: { name: 'Material', enabled: false, value: false }, + concentration: { name: 'Concentration', enabled: false, value: false }, + ritual: { name: 'Ritual', enabled: false, value: false }, + }, + } + }, computed: { - computedSpells(){ + computedSpells() { return spellsWithSubheaders(this.spells); }, - canCast(){ + canCast() { if (!this.selectedSpell || !this.selectedSlotId) return false; return this.canCastSpellWithSlot( this.selectedSpell, this.selectedSlotId, this.selectedSlot ); }, - filtersApplied(){ - for (let key in this.booleanFilters){ - if (this.booleanFilters[key].enabled){ + filtersApplied() { + for (let key in this.booleanFilters) { + if (this.booleanFilters[key].enabled) { return true; } } @@ -250,15 +252,15 @@ export default { }, watch: { selectedSpellId: { - handler(spellId){ + handler(spellId) { this.selectedSpell = CreatureProperties.findOne(spellId) }, immediate: true }, selectedSpell: { - handler(spell){ + handler(spell) { if (!spell) return; - if(spell.level === 0 || spell.castWithoutSpellSlots){ + if (spell.level === 0 || spell.castWithoutSpellSlots) { this.selectedSlotId = 'no-slot'; } else if ( !this.selectedSlotId || @@ -270,13 +272,13 @@ export default { 'ancestors.id': this.creatureId, ...slotFilter }, { - sort: {'spellSlotLevel.value': 1, order: 1}, + sort: { 'spellSlotLevel.value': 1, order: 1 }, }).fetch(), slot => { return this.canCastSpellWithSlot(spell, slot._id, slot) } ); - if (newSlot){ + if (newSlot) { this.selectedSlotId = newSlot._id; } } @@ -284,45 +286,45 @@ export default { immediate: true, }, selectedSlotId: { - handler(slotId){ + handler(slotId) { this.selectedSlot = CreatureProperties.findOne(slotId); }, immediate: true }, - selectedSlot:{ - handler(slot){ + selectedSlot: { + handler(slot) { if (!slot) return; if (!this.selectedSpell) return; - if(this.selectedSpell.level > slot.spellSlotLevel.value){ + if (this.selectedSpell.level > slot.spellSlotLevel.value) { this.selectedSpellId = undefined; } }, immediate: true, }, }, - mounted(){ - if (this.selectedSpellId){ - this.$vuetify.goTo('.spell.v-list-item--active', {container: '.right'}); + mounted() { + if (this.selectedSpellId) { + this.$vuetify.goTo('.spell.v-list-item--active', { container: '.right' }); } }, methods: { - clearBooleanFilters(){ - for (let key in this.booleanFilters){ + clearBooleanFilters() { + for (let key in this.booleanFilters) { this.booleanFilters[key].enabled = false; } }, - spellDialog(_id){ + spellDialog(_id) { this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `spell-info-btn-${_id}`, - data: {_id}, - }); + component: 'creature-property-dialog', + elementId: `spell-info-btn-${_id}`, + data: { _id }, + }); }, - searchChanged(val, ack){ + searchChanged(val, ack) { this.searchValue = val; setTimeout(ack, 200); }, - canCastSpellWithSlot(spell, slotId, slot){ + canCastSpellWithSlot(spell, slotId, slot) { if (slot && !slot.value) return false; if (!spell) return true; if (!slotId) return true; @@ -341,7 +343,7 @@ export default { ) ) }, - cast({advantage}){ + cast({ advantage }) { let selectedSlotId = this.selectedSlotId; if (selectedSlotId === 'no-slot') selectedSlotId = undefined; this.$store.dispatch('popDialogStack', { @@ -352,45 +354,45 @@ export default { } }, meteor: { - spells(){ + spells() { let filter = { 'ancestors.id': this.creatureId, - removed: {$ne: true}, - inactive: {$ne: true}, + removed: { $ne: true }, + inactive: { $ne: true }, $or: [ - {prepared: true}, - {alwaysPrepared: true}, + { prepared: true }, + { alwaysPrepared: true }, ], }; // Apply the filters from the filter menu - for (let key in this.booleanFilters){ - if (this.booleanFilters[key].enabled){ + for (let key in this.booleanFilters) { + if (this.booleanFilters[key].enabled) { let value = this.booleanFilters[key].value; - if (key === 'material'){ - filter[key] = {$exists: this.booleanFilters[key].value}; + if (key === 'material') { + filter[key] = { $exists: this.booleanFilters[key].value }; } else { - filter[key] = value ? true: {$ne: true}; + filter[key] = value ? true : { $ne: true }; } } } // Apply the search string to the name field - if (this.searchValue){ + if (this.searchValue) { filter.name = { $regex: this.searchValue.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), $options: 'i' }; } return CreatureProperties.find(filter, { - sort: {order: 1} + sort: { order: 1 } }); }, - spellSlots(){ + spellSlots() { return CreatureProperties.find({ 'ancestors.id': this.creatureId, ...slotFilter }, { - sort: {'spellSlotLevel.value': 1, order: 1}, + sort: { 'spellSlotLevel.value': 1, order: 1 }, }); }, }, @@ -398,10 +400,11 @@ export default { diff --git a/app/imports/ui/properties/components/spells/SpellList.vue b/app/imports/ui/properties/components/spells/SpellList.vue index 3d1d6333..50f70bfc 100644 --- a/app/imports/ui/properties/components/spells/SpellList.vue +++ b/app/imports/ui/properties/components/spells/SpellList.vue @@ -62,48 +62,50 @@ export default { }, preparingSpells: Boolean, }, - data(){ return { - dataSpells: [], - }}, + data() { + return { + dataSpells: [], + } + }, computed: { - levels(){ + levels() { let levels = new Set(); this.spells.forEach(spell => levels.add(spell.level)); return levels; }, computedSpells: { - get(){ + get() { return spellsWithSubheaders(this.dataSpells); }, - set(value){ + set(value) { this.dataSpells = value; }, } }, watch: { - spells(value){ + spells(value) { this.dataSpells = spellsWithSubheaders(value); } }, - mounted(){ + mounted() { this.dataSpells = spellsWithSubheaders(this.spells); }, methods: { - clickProperty(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `spell-list-tile-${_id}`, - data: {_id}, - }); - }, - change({added, moved}){ + clickProperty(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: `spell-list-tile-${_id}`, + data: { _id }, + }); + }, + change({ added, moved }) { let event = added || moved; - if (event){ + if (event) { // If this spell is now adjacent to another, set the order accordingly let order; let before = this.dataSpells[event.newIndex - 1]; let after = this.dataSpells[event.newIndex + 1]; - if (before && before._id){ + if (before && before._id) { order = before.order + 0.5; } else if (after && after._id) { order = after.order - 0.5; @@ -121,9 +123,10 @@ export default { }); } }, - } + } } diff --git a/app/imports/ui/properties/components/spells/SpellListCard.vue b/app/imports/ui/properties/components/spells/SpellListCard.vue index c45c7cc3..4dd5edc4 100644 --- a/app/imports/ui/properties/components/spells/SpellListCard.vue +++ b/app/imports/ui/properties/components/spells/SpellListCard.vue @@ -63,32 +63,34 @@ import SpellList from '/imports/ui/properties/components/spells/SpellList.vue'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; export default { - components: { - ToolbarCard, + components: { + ToolbarCard, SpellList, - }, - props: { - model: { + }, + props: { + model: { type: Object, required: true, }, - organize: Boolean, - }, - data(){ return { - preparingSpells: false, - }}, + organize: Boolean, + }, + data() { + return { + preparingSpells: false, + } + }, meteor: { - spells(){ + spells() { let filter = { 'ancestors.id': this.model._id, type: 'spell', - removed: {$ne: true}, + removed: { $ne: true }, }; - if (this.preparingSpells){ - filter.deactivatedByAncestor = {$ne: true}; - filter.deactivatedByToggle = {$ne: true}; + if (this.preparingSpells) { + filter.deactivatedByAncestor = { $ne: true }; + filter.deactivatedByToggle = { $ne: true }; } else { - filter.inactive = {$ne: true}; + filter.inactive = { $ne: true }; } return CreatureProperties.find(filter, { sort: { @@ -97,35 +99,36 @@ export default { } }); }, - numPrepared(){ + numPrepared() { return CreatureProperties.find({ 'ancestors.id': this.model._id, type: 'spell', - removed: {$ne: true}, + removed: { $ne: true }, prepared: true, - alwaysPrepared: {$ne: true}, - deactivatedByAncestor: {$ne: true}, - deactivatedByToggle: {$ne: true}, + alwaysPrepared: { $ne: true }, + deactivatedByAncestor: { $ne: true }, + deactivatedByToggle: { $ne: true }, }).count(); }, - preparedError(){ + preparedError() { if (!this.model.maxPrepared) return; let numPrepared = this.numPrepared; let maxPrepared = this.model.maxPrepared.value || 0; return numPrepared !== maxPrepared }, }, - methods: { - clickSpellList(_id){ - this.$store.commit('pushDialogStack', { - component: 'creature-property-dialog', - elementId: `${_id}`, - data: {_id}, - }); - }, - } + methods: { + clickSpellList(_id) { + this.$store.commit('pushDialogStack', { + component: 'creature-property-dialog', + elementId: `${_id}`, + data: { _id }, + }); + }, + } }; diff --git a/app/imports/ui/properties/components/spells/SpellListTile.vue b/app/imports/ui/properties/components/spells/SpellListTile.vue index 1e6af252..20122630 100644 --- a/app/imports/ui/properties/components/spells/SpellListTile.vue +++ b/app/imports/ui/properties/components/spells/SpellListTile.vue @@ -67,10 +67,10 @@ export default { disabled: Boolean, }, computed: { - hasClickListener(){ + hasClickListener() { return this.$listeners && !!this.$listeners.click; }, - spellComponents(){ + spellComponents() { let components = []; if (this.model.ritual) components.push('R'); if (this.model.concentration) components.push('C'); @@ -81,10 +81,10 @@ export default { }, }, methods: { - click(e){ - this.$emit('click', e); - }, - setPrepared(val, ack){ + click(e) { + this.$emit('click', e); + }, + setPrepared(val, ack) { updateCreatureProperty.call({ _id: this.model._id, path: ['prepared'], @@ -99,13 +99,17 @@ export default { .spell-avatar { min-width: 32px; } + .spell { background-color: inherit; } -.primary--text .v-icon, .primary--text .v-list__tile__sub-title { + +.primary--text .v-icon, +.primary--text .v-list__tile__sub-title { color: #b71c1c } -.theme--light.info-icon{ - color: rgba(0,0,0,.54) !important; + +.theme--light.info-icon { + color: rgba(0, 0, 0, .54) !important; } diff --git a/app/imports/ui/properties/forms/AdjustmentForm.vue b/app/imports/ui/properties/forms/AdjustmentForm.vue index 94d419c4..31712722 100644 --- a/app/imports/ui/properties/forms/AdjustmentForm.vue +++ b/app/imports/ui/properties/forms/AdjustmentForm.vue @@ -81,60 +81,63 @@ import propertyFormMixin from '/imports/ui/properties/forms/shared/propertyFormM export default { mixins: [propertyFormMixin, attributeListMixin], - props: { - parentTarget: { - type: String, + props: { + parentTarget: { + type: String, default: undefined, - }, - }, - data(){return { - adjustmentOps: [ - {text: 'Damage', value: 'increment'}, - {text: 'Set', value: 'set'}, - ], - damageHint: 'The amount of damage to apply to the selected stat, can be a calculation or roll. Negative values will restore the selected from previous damage. If the operation is set, this is the final value of the stat instead.', - setHint: 'The value of the stat after applying this adjustment. The stat\'s value can\'t exceed its total', - }}, - computed: { - targetOptions(){ - if (this.parentTarget === 'singleTarget') { - return [ - { - text: 'Self', - value: 'self', - }, { - text: 'Target', - value: 'every', - }, - ]; - } else { - return [ - { - text: 'Self', - value: 'self', - }, { - text: 'Target', - value: 'target', - }, - ]; - } - }, - targetOptionHint(){ - let hints = { - self: 'The damage will be applied to the character\'s own attribute when taking the action', - target: 'The damage will be applied to the target of the action', - each: 'The damage will be rolled separately for each of the targets of the action', - every: 'The damage will be rolled once and applied to each of the targets of the action', - }; - if (this.parentTarget === 'singleTarget'){ - hints.each = hints.target; - hints.every = hints.target; - } - return hints[this.model.target]; - } - }, + }, + }, + data() { + return { + adjustmentOps: [ + { text: 'Damage', value: 'increment' }, + { text: 'Set', value: 'set' }, + ], + damageHint: 'The amount of damage to apply to the selected stat, can be a calculation or roll. Negative values will restore the selected from previous damage. If the operation is set, this is the final value of the stat instead.', + setHint: 'The value of the stat after applying this adjustment. The stat\'s value can\'t exceed its total', + } + }, + computed: { + targetOptions() { + if (this.parentTarget === 'singleTarget') { + return [ + { + text: 'Self', + value: 'self', + }, { + text: 'Target', + value: 'every', + }, + ]; + } else { + return [ + { + text: 'Self', + value: 'self', + }, { + text: 'Target', + value: 'target', + }, + ]; + } + }, + targetOptionHint() { + let hints = { + self: 'The damage will be applied to the character\'s own attribute when taking the action', + target: 'The damage will be applied to the target of the action', + each: 'The damage will be rolled separately for each of the targets of the action', + every: 'The damage will be rolled once and applied to each of the targets of the action', + }; + if (this.parentTarget === 'singleTarget') { + hints.each = hints.target; + hints.every = hints.target; + } + return hints[this.model.target]; + } + }, } diff --git a/app/imports/ui/properties/forms/AttributeForm.vue b/app/imports/ui/properties/forms/AttributeForm.vue index 0b23d1df..42814d86 100644 --- a/app/imports/ui/properties/forms/AttributeForm.vue +++ b/app/imports/ui/properties/forms/AttributeForm.vue @@ -140,9 +140,7 @@ - + diff --git a/app/imports/ui/properties/forms/AttributesConsumedListForm.vue b/app/imports/ui/properties/forms/AttributesConsumedListForm.vue index b0a847de..97ff2d81 100644 --- a/app/imports/ui/properties/forms/AttributesConsumedListForm.vue +++ b/app/imports/ui/properties/forms/AttributesConsumedListForm.vue @@ -29,13 +29,13 @@ diff --git a/app/imports/ui/properties/forms/BranchForm.vue b/app/imports/ui/properties/forms/BranchForm.vue index d1aa6ec9..1ad49fb4 100644 --- a/app/imports/ui/properties/forms/BranchForm.vue +++ b/app/imports/ui/properties/forms/BranchForm.vue @@ -54,45 +54,48 @@ diff --git a/app/imports/ui/properties/forms/BuffForm.vue b/app/imports/ui/properties/forms/BuffForm.vue index a7c3b0dd..ade759e4 100644 --- a/app/imports/ui/properties/forms/BuffForm.vue +++ b/app/imports/ui/properties/forms/BuffForm.vue @@ -44,9 +44,7 @@ > - + diff --git a/app/imports/ui/properties/forms/ClassForm.vue b/app/imports/ui/properties/forms/ClassForm.vue index d301b750..f4bd101e 100644 --- a/app/imports/ui/properties/forms/ClassForm.vue +++ b/app/imports/ui/properties/forms/ClassForm.vue @@ -1,8 +1,6 @@ diff --git a/app/imports/ui/properties/forms/ContainerForm.vue b/app/imports/ui/properties/forms/ContainerForm.vue index 78990b4d..58f127e0 100644 --- a/app/imports/ui/properties/forms/ContainerForm.vue +++ b/app/imports/ui/properties/forms/ContainerForm.vue @@ -63,9 +63,7 @@ - + diff --git a/app/imports/ui/properties/forms/DamageForm.vue b/app/imports/ui/properties/forms/DamageForm.vue index 98d92e3d..1faa66f3 100644 --- a/app/imports/ui/properties/forms/DamageForm.vue +++ b/app/imports/ui/properties/forms/DamageForm.vue @@ -76,45 +76,48 @@ import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js'; export default { mixins: [propertyFormMixin], - props: { - parentTarget: { - type: String, + props: { + parentTarget: { + type: String, default: undefined, - }, - }, - data(){return{ - DAMAGE_TYPES, - damageTypeRules: [ - value => { - if (!value) return 'Damage type is required'; - if (!VARIABLE_NAME_REGEX.test(value)){ - return `${value} is not a valid damage name` + }, + }, + data() { + return { + DAMAGE_TYPES, + damageTypeRules: [ + value => { + if (!value) return 'Damage type is required'; + if (!VARIABLE_NAME_REGEX.test(value)) { + return `${value} is not a valid damage name` + } } - } - ], - }}, - computed: { - targetOptions(){ - return [ - { - text: 'Self', - value: 'self', - }, { - text: 'Target', - value: 'target', - }, - ]; - }, - targetOptionHint(){ - let hints = { - self: 'The damage will be applied to the character taking the action', - target: 'The damage will be applied to the target of the action', - }; - return hints[this.model.target]; - } - }, + ], + } + }, + computed: { + targetOptions() { + return [ + { + text: 'Self', + value: 'self', + }, { + text: 'Target', + value: 'target', + }, + ]; + }, + targetOptionHint() { + let hints = { + self: 'The damage will be applied to the character taking the action', + target: 'The damage will be applied to the target of the action', + }; + return hints[this.model.target]; + } + }, } diff --git a/app/imports/ui/properties/forms/DamageMultiplierForm.vue b/app/imports/ui/properties/forms/DamageMultiplierForm.vue index 7705196b..551f1514 100644 --- a/app/imports/ui/properties/forms/DamageMultiplierForm.vue +++ b/app/imports/ui/properties/forms/DamageMultiplierForm.vue @@ -52,9 +52,7 @@ > - + diff --git a/app/imports/ui/properties/forms/EffectForm.vue b/app/imports/ui/properties/forms/EffectForm.vue index 9ef23c9a..694db21d 100644 --- a/app/imports/ui/properties/forms/EffectForm.vue +++ b/app/imports/ui/properties/forms/EffectForm.vue @@ -29,9 +29,7 @@ slot="item" slot-scope="item" > - + {{ getEffectIcon(item.item.value, 1) }} {{ item.item.text }} @@ -157,9 +155,7 @@ - + diff --git a/app/imports/ui/properties/forms/FeatureForm.vue b/app/imports/ui/properties/forms/FeatureForm.vue index cb900962..c3f85735 100644 --- a/app/imports/ui/properties/forms/FeatureForm.vue +++ b/app/imports/ui/properties/forms/FeatureForm.vue @@ -46,49 +46,52 @@ diff --git a/app/imports/ui/properties/forms/FolderForm.vue b/app/imports/ui/properties/forms/FolderForm.vue index 84f29b84..77c96aec 100644 --- a/app/imports/ui/properties/forms/FolderForm.vue +++ b/app/imports/ui/properties/forms/FolderForm.vue @@ -17,9 +17,7 @@ - + diff --git a/app/imports/ui/properties/forms/ItemForm.vue b/app/imports/ui/properties/forms/ItemForm.vue index ced109d9..d8097daa 100644 --- a/app/imports/ui/properties/forms/ItemForm.vue +++ b/app/imports/ui/properties/forms/ItemForm.vue @@ -158,9 +158,9 @@ import FormSection from '/imports/ui/properties/forms/shared/FormSection.vue'; import propertyFormMixin from '/imports/ui/properties/forms/shared/propertyFormMixin.js'; export default { - components: { - FormSection, - }, + components: { + FormSection, + }, mixins: [propertyFormMixin], - } +} diff --git a/app/imports/ui/properties/forms/ItemsConsumedListForm.vue b/app/imports/ui/properties/forms/ItemsConsumedListForm.vue index 80069155..97531ec6 100644 --- a/app/imports/ui/properties/forms/ItemsConsumedListForm.vue +++ b/app/imports/ui/properties/forms/ItemsConsumedListForm.vue @@ -29,13 +29,13 @@ diff --git a/app/imports/ui/properties/forms/ProficiencyForm.vue b/app/imports/ui/properties/forms/ProficiencyForm.vue index 87b35b4a..4fcf2825 100644 --- a/app/imports/ui/properties/forms/ProficiencyForm.vue +++ b/app/imports/ui/properties/forms/ProficiencyForm.vue @@ -48,17 +48,18 @@ diff --git a/app/imports/ui/properties/forms/ResourcesForm.vue b/app/imports/ui/properties/forms/ResourcesForm.vue index 5c3e92d9..e3fc0dcb 100644 --- a/app/imports/ui/properties/forms/ResourcesForm.vue +++ b/app/imports/ui/properties/forms/ResourcesForm.vue @@ -55,54 +55,57 @@ diff --git a/app/imports/ui/properties/forms/RollForm.vue b/app/imports/ui/properties/forms/RollForm.vue index 26432790..c06ceaa6 100644 --- a/app/imports/ui/properties/forms/RollForm.vue +++ b/app/imports/ui/properties/forms/RollForm.vue @@ -41,7 +41,7 @@ > - + diff --git a/app/imports/ui/properties/forms/SavingThrowForm.vue b/app/imports/ui/properties/forms/SavingThrowForm.vue index 1fc03b68..8e0c5540 100644 --- a/app/imports/ui/properties/forms/SavingThrowForm.vue +++ b/app/imports/ui/properties/forms/SavingThrowForm.vue @@ -88,24 +88,24 @@ import propertyFormMixin from '/imports/ui/properties/forms/shared/propertyFormM export default { mixins: [saveListMixin, propertyFormMixin], computed: { - targetOptions(){ - return [ - { - text: 'Self', - value: 'self', - }, { - text: 'Target', - value: 'target', - }, - ]; - }, - targetOptionHint(){ - let hints = { - self: 'The save will be applied to the character taking the action', - target: 'The save will be applied to the targets of the action', - }; - return hints[this.model.target]; - } - }, + targetOptions() { + return [ + { + text: 'Self', + value: 'self', + }, { + text: 'Target', + value: 'target', + }, + ]; + }, + targetOptionHint() { + let hints = { + self: 'The save will be applied to the character taking the action', + target: 'The save will be applied to the targets of the action', + }; + return hints[this.model.target]; + } + }, }; diff --git a/app/imports/ui/properties/forms/SkillForm.vue b/app/imports/ui/properties/forms/SkillForm.vue index 2854013e..91d30970 100644 --- a/app/imports/ui/properties/forms/SkillForm.vue +++ b/app/imports/ui/properties/forms/SkillForm.vue @@ -53,9 +53,7 @@ - + diff --git a/app/imports/ui/properties/forms/SlotFillerForm.vue b/app/imports/ui/properties/forms/SlotFillerForm.vue index 64ce1c51..28890a30 100644 --- a/app/imports/ui/properties/forms/SlotFillerForm.vue +++ b/app/imports/ui/properties/forms/SlotFillerForm.vue @@ -95,20 +95,20 @@ diff --git a/app/imports/ui/properties/forms/SlotForm.vue b/app/imports/ui/properties/forms/SlotForm.vue index 6c001c2c..f2dc7c9b 100644 --- a/app/imports/ui/properties/forms/SlotForm.vue +++ b/app/imports/ui/properties/forms/SlotForm.vue @@ -72,13 +72,11 @@ @change="change('slotTags', ...arguments)" /> - +
- +
diff --git a/app/imports/ui/properties/forms/SpellForm.vue b/app/imports/ui/properties/forms/SpellForm.vue index db36d5b0..4544857c 100644 --- a/app/imports/ui/properties/forms/SpellForm.vue +++ b/app/imports/ui/properties/forms/SpellForm.vue @@ -247,9 +247,7 @@ /> - + diff --git a/app/imports/ui/properties/forms/ToggleForm.vue b/app/imports/ui/properties/forms/ToggleForm.vue index f3d01b0f..5f98729c 100644 --- a/app/imports/ui/properties/forms/ToggleForm.vue +++ b/app/imports/ui/properties/forms/ToggleForm.vue @@ -41,9 +41,7 @@ cols="12" md="6" > - + - + diff --git a/app/imports/ui/properties/forms/shared/FormSection.vue b/app/imports/ui/properties/forms/shared/FormSection.vue index 96946f77..88c8c279 100644 --- a/app/imports/ui/properties/forms/shared/FormSection.vue +++ b/app/imports/ui/properties/forms/shared/FormSection.vue @@ -22,16 +22,16 @@ diff --git a/app/imports/ui/properties/forms/shared/FormSections.vue b/app/imports/ui/properties/forms/shared/FormSections.vue index e7e8a738..70701ed4 100644 --- a/app/imports/ui/properties/forms/shared/FormSections.vue +++ b/app/imports/ui/properties/forms/shared/FormSections.vue @@ -8,5 +8,5 @@ diff --git a/app/imports/ui/properties/forms/shared/ProficiencySelect.vue b/app/imports/ui/properties/forms/shared/ProficiencySelect.vue index 51e1dc4c..1af7095a 100644 --- a/app/imports/ui/properties/forms/shared/ProficiencySelect.vue +++ b/app/imports/ui/properties/forms/shared/ProficiencySelect.vue @@ -22,11 +22,11 @@ diff --git a/app/imports/ui/properties/forms/shared/schemaFormMixin.js b/app/imports/ui/properties/forms/shared/schemaFormMixin.js index e1d3a349..5db234da 100644 --- a/app/imports/ui/properties/forms/shared/schemaFormMixin.js +++ b/app/imports/ui/properties/forms/shared/schemaFormMixin.js @@ -4,9 +4,9 @@ */ import { get, toPath } from 'lodash'; -function resolvePath(model, path, set){ +function resolvePath(model, path, set) { let arrayPath = toPath(path); - if (arrayPath.length === 1){ + if (arrayPath.length === 1) { return { object: model, key: arrayPath[0] }; } let key = arrayPath.slice(-1); @@ -15,67 +15,69 @@ function resolvePath(model, path, set){ // Ensure that nested objects exist before navigating them objectPath.forEach(pathKey => { let newObject = object[pathKey]; - if (!newObject){ + if (!newObject) { newObject = {}; set(object, pathKey, newObject); } object = newObject; }); - return {object, key}; + return { object, key }; } const schemaFormMixin = { - data(){ return { - valid: true, - };}, - computed: { - errors(){ - this.valid = true; - if (!this.model){ - throw new Error('this.model must be set'); - } - if (!this.validationContext) return {}; - let cleanModel = this.validationContext.clean(this.model, { - getAutoValues: false, - }); - this.validationContext.validate(cleanModel); - let errors = {}; - this.validationContext.validationErrors().forEach(error => { - if (this.valid) this.valid = false; - errors[error.name] = this.schema.messageForError(error); - }); - return errors; - }, - }, - methods: { + data() { + return { + valid: true, + }; + }, + computed: { + errors() { + this.valid = true; + if (!this.model) { + throw new Error('this.model must be set'); + } + if (!this.validationContext) return {}; + let cleanModel = this.validationContext.clean(this.model, { + getAutoValues: false, + }); + this.validationContext.validate(cleanModel); + let errors = {}; + this.validationContext.validationErrors().forEach(error => { + if (this.valid) this.valid = false; + errors[error.name] = this.schema.messageForError(error); + }); + return errors; + }, + }, + methods: { // Sets the value at the given path - change({path, value, ack}){ - let {object, key} = resolvePath(this.model, path, this.$set); + change({ path, value, ack }) { + let { object, key } = resolvePath(this.model, path, this.$set); - this.$set(object, key, value); - if (ack) ack(); - }, - push({path, value, ack}){ + this.$set(object, key, value); + if (ack) ack(); + }, + push({ path, value, ack }) { let array = get(this.model, path); - if (array === undefined){ - let {object, key} = resolvePath(this.model, path, this.$set); + if (array === undefined) { + let { object, key } = resolvePath(this.model, path, this.$set); this.$set(object, key, [value]); - } else if (!array.push){ + } else if (!array.push) { throw `${path.join('.')} is ${array}, doesn't have "push"` } else { array.push(value); } - if (ack) ack(); + if (ack) ack(); }, - pull({path, ack}){ - let {object, key} = resolvePath(this.model, path, this.$set); - if (!object || !object.splice){ + pull({ path, ack }) { + let { object, key } = resolvePath(this.model, path, this.$set); + if (!object || !object.splice) { throw `${path.join('.')} is ${object}, doesnt have "splice"` } object.splice(key, 1); if (ack) ack(); }, - }, + }, }; export default schemaFormMixin; diff --git a/app/imports/ui/properties/shared/ProficiencyIcon.vue b/app/imports/ui/properties/shared/ProficiencyIcon.vue index 91249fc3..223ef725 100644 --- a/app/imports/ui/properties/shared/ProficiencyIcon.vue +++ b/app/imports/ui/properties/shared/ProficiencyIcon.vue @@ -8,16 +8,16 @@ import getProficiencyIcon from '/imports/ui/utility/getProficiencyIcon.js'; export default { - props: { - value: { + props: { + value: { type: Number, default: undefined, }, - }, - computed: { - displayedIcon(){ + }, + computed: { + displayedIcon(){ return getProficiencyIcon(this.value); - } - } + } + } } diff --git a/app/imports/ui/properties/shared/PropertyIcon.vue b/app/imports/ui/properties/shared/PropertyIcon.vue index bf173aef..73a241db 100644 --- a/app/imports/ui/properties/shared/PropertyIcon.vue +++ b/app/imports/ui/properties/shared/PropertyIcon.vue @@ -18,8 +18,8 @@ import { getPropertyIcon } from '/imports/constants/PROPERTIES.js'; export default { - props: { - model: { + props: { + model: { type: Object, default: () => ({}), }, @@ -28,17 +28,18 @@ export default { default: undefined, }, disabled: Boolean, - }, - computed: { - icon(){ - return getPropertyIcon(this.model && this.model.type); - }, - }, + }, + computed: { + icon() { + return getPropertyIcon(this.model && this.model.type); + }, + }, } diff --git a/app/imports/ui/properties/shared/PropertySelector.vue b/app/imports/ui/properties/shared/PropertySelector.vue index 36670fe7..8fc32b7e 100644 --- a/app/imports/ui/properties/shared/PropertySelector.vue +++ b/app/imports/ui/properties/shared/PropertySelector.vue @@ -1,8 +1,6 @@ diff --git a/app/imports/ui/properties/viewers/EffectViewer.vue b/app/imports/ui/properties/viewers/EffectViewer.vue index ef72d816..5880fc10 100644 --- a/app/imports/ui/properties/viewers/EffectViewer.vue +++ b/app/imports/ui/properties/viewers/EffectViewer.vue @@ -6,9 +6,7 @@ class="layout" style="overflow: hidden;" > - + {{ effectIcon }} {{ operation }} @@ -77,71 +75,75 @@ diff --git a/app/imports/ui/properties/viewers/FeatureViewer.vue b/app/imports/ui/properties/viewers/FeatureViewer.vue index 4727df07..ae5c405b 100644 --- a/app/imports/ui/properties/viewers/FeatureViewer.vue +++ b/app/imports/ui/properties/viewers/FeatureViewer.vue @@ -16,9 +16,10 @@ diff --git a/app/imports/ui/properties/viewers/FolderViewer.vue b/app/imports/ui/properties/viewers/FolderViewer.vue index 352db109..51a51a76 100644 --- a/app/imports/ui/properties/viewers/FolderViewer.vue +++ b/app/imports/ui/properties/viewers/FolderViewer.vue @@ -5,9 +5,10 @@ diff --git a/app/imports/ui/properties/viewers/ItemViewer.vue b/app/imports/ui/properties/viewers/ItemViewer.vue index d5f07aab..0db65ce7 100644 --- a/app/imports/ui/properties/viewers/ItemViewer.vue +++ b/app/imports/ui/properties/viewers/ItemViewer.vue @@ -24,9 +24,7 @@ v-if="model.value !== undefined" name="value" > -
+
- + -
+
- + Equipped - + diff --git a/app/imports/ui/properties/viewers/RollViewer.vue b/app/imports/ui/properties/viewers/RollViewer.vue index d00aeed1..31e87bbf 100644 --- a/app/imports/ui/properties/viewers/RollViewer.vue +++ b/app/imports/ui/properties/viewers/RollViewer.vue @@ -17,9 +17,9 @@ diff --git a/app/imports/ui/properties/viewers/SavingThrowViewer.vue b/app/imports/ui/properties/viewers/SavingThrowViewer.vue index 02b4fbcb..59feea7a 100644 --- a/app/imports/ui/properties/viewers/SavingThrowViewer.vue +++ b/app/imports/ui/properties/viewers/SavingThrowViewer.vue @@ -22,9 +22,9 @@ diff --git a/app/imports/ui/properties/viewers/SkillViewer.vue b/app/imports/ui/properties/viewers/SkillViewer.vue index 651fd9c5..db6609c5 100644 --- a/app/imports/ui/properties/viewers/SkillViewer.vue +++ b/app/imports/ui/properties/viewers/SkillViewer.vue @@ -133,42 +133,44 @@ export default { AttributeEffect, SkillProficiency, }, - mixins: [propertyViewerMixin], + mixins: [propertyViewerMixin], inject: { context: { default: {} } }, - data(){return { - proficiencyText: { - 0: 'Not proficient', - 1: 'Proficient', - 0.49: 'Half proficiency bonus rounded down', - 0.5: 'Half proficiency bonus rounded up', - 2: 'Double proficiency bonus', - }, - skillTypes: { - skill: 'Skill', - save: 'Save', - check: 'Check', - tool: 'Tool', - weapon: 'Weapon', - armor: 'Armor', - language: 'Language', - utility: 'Utility', - }, - }}, + data() { + return { + proficiencyText: { + 0: 'Not proficient', + 1: 'Proficient', + 0.49: 'Half proficiency bonus rounded down', + 0.5: 'Half proficiency bonus rounded up', + 2: 'Double proficiency bonus', + }, + skillTypes: { + skill: 'Skill', + save: 'Save', + check: 'Check', + tool: 'Tool', + weapon: 'Weapon', + armor: 'Armor', + language: 'Language', + utility: 'Utility', + }, + } + }, computed: { - displayedModifier(){ - let mod = this.model.value; - if (this.model.fail){ - return 'fail'; - } else { - return numberToSignedString(mod); - } - }, - icon(){ + displayedModifier() { + let mod = this.model.value; + if (this.model.fail) { + return 'fail'; + } else { + return numberToSignedString(mod); + } + }, + icon() { return getProficiencyIcon(this.model.proficiency); - }, - passiveScore(){ + }, + passiveScore() { return 10 + this.model.value + this.model.passiveBonus; }, effects() { @@ -178,53 +180,53 @@ export default { methods: { numberToSignedString, isFinite: Number.isFinite, - clickEffect(id){ + clickEffect(id) { this.$store.commit('pushDialogStack', { component: 'creature-property-dialog', elementId: `${id}`, - data: {_id: id}, + data: { _id: id }, }); }, }, meteor: { - variables(){ - return CreatureVariables.findOne({_creatureId: this.context.creatureId}) || {}; + variables() { + return CreatureVariables.findOne({ _creatureId: this.context.creatureId }) || {}; }, - baseProficiencies(){ - if (this.context.creatureId){ + baseProficiencies() { + if (this.context.creatureId) { let creatureId = this.context.creatureId; return CreatureProperties.find({ 'ancestors.id': creatureId, type: 'skill', variableName: this.model.variableName, - removed: {$ne: true}, - inactive: {$ne: true}, - }).map( prop => ({ + removed: { $ne: true }, + inactive: { $ne: true }, + }).map(prop => ({ _id: prop._id, name: 'Skill base proficiency', value: prop.baseProficiency, stats: [prop.variableName], ancestors: prop.ancestors, - }) ).filter(prof => prof.value); + })).filter(prof => prof.value); } else { return []; } }, - proficiencies(){ + proficiencies() { let creatureId = this.context.creatureId; - if (creatureId){ + if (creatureId) { return CreatureProperties.find({ 'ancestors.id': creatureId, stats: this.model.variableName, type: 'proficiency', - removed: {$ne: true}, - inactive: {$ne: true}, + removed: { $ne: true }, + inactive: { $ne: true }, }).fetch(); } else { return []; } }, - ability(){ + ability() { let creatureId = this.context.creatureId; let ability = this.model.ability; if (!creatureId || !ability) return; @@ -232,21 +234,21 @@ export default { 'ancestors.id': creatureId, variableName: ability, type: 'attribute', - removed: {$ne: true}, - inactive: {$ne: true}, - overridden: {$ne: true}, + removed: { $ne: true }, + inactive: { $ne: true }, + overridden: { $ne: true }, }); if (!abilityProp) return; return { _id: abilityProp._id, name: abilityProp.name, operation: 'add', - amount: {value: abilityProp.modifier}, + amount: { value: abilityProp.modifier }, stats: [this.model.variableName], ancestors: abilityProp.ancestors, } }, - proficiencyBonus(){ + proficiencyBonus() { let creatureId = this.context.creatureId; if (!creatureId) return; return this.variables.proficiencyBonus && @@ -257,4 +259,5 @@ export default { diff --git a/app/imports/ui/properties/viewers/SlotFillerViewer.vue b/app/imports/ui/properties/viewers/SlotFillerViewer.vue index 6ebf8a36..d3cb60c5 100644 --- a/app/imports/ui/properties/viewers/SlotFillerViewer.vue +++ b/app/imports/ui/properties/viewers/SlotFillerViewer.vue @@ -32,32 +32,30 @@ name="Description" :cols="{cols: 12}" > - +
diff --git a/app/imports/ui/properties/viewers/SlotViewer.vue b/app/imports/ui/properties/viewers/SlotViewer.vue index 36e432f1..55ceeb8d 100644 --- a/app/imports/ui/properties/viewers/SlotViewer.vue +++ b/app/imports/ui/properties/viewers/SlotViewer.vue @@ -60,34 +60,34 @@ diff --git a/app/imports/ui/properties/viewers/SpellListViewer.vue b/app/imports/ui/properties/viewers/SpellListViewer.vue index 9b4c9d49..f7c35b57 100644 --- a/app/imports/ui/properties/viewers/SpellListViewer.vue +++ b/app/imports/ui/properties/viewers/SpellListViewer.vue @@ -37,6 +37,6 @@ diff --git a/app/imports/ui/properties/viewers/SpellViewer.vue b/app/imports/ui/properties/viewers/SpellViewer.vue index 35b31e7b..ee8085b2 100644 --- a/app/imports/ui/properties/viewers/SpellViewer.vue +++ b/app/imports/ui/properties/viewers/SpellViewer.vue @@ -43,12 +43,12 @@ export default { components: { ActionViewer, }, - mixins: [propertyViewerMixin], - computed:{ - levelText(){ + mixins: [propertyViewerMixin], + computed: { + levelText() { return levelText[this.model.level] }, - spellComponents(){ + spellComponents() { let components = []; if (this.model.ritual) components.push('Ritual'); if (this.model.concentration) components.push('Concentration'); @@ -62,4 +62,5 @@ export default { diff --git a/app/imports/ui/properties/viewers/ToggleViewer.vue b/app/imports/ui/properties/viewers/ToggleViewer.vue index 666c184f..f2b9037a 100644 --- a/app/imports/ui/properties/viewers/ToggleViewer.vue +++ b/app/imports/ui/properties/viewers/ToggleViewer.vue @@ -11,9 +11,7 @@ name="Status" :value="model.enabled ? 'Enabled' : 'Disabled'" /> -