From 88bc223daa1869e965351365180856125211d937 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 20 Apr 2022 13:56:06 +0200 Subject: [PATCH 01/56] Began working on build tab --- .../ui/creature/CreatureFormDialog.vue | 7 +- .../ui/creature/character/CharacterSheet.vue | 7 +- .../character/CharacterSheetToolbar.vue | 5 +- .../ui/creature/character/CreatureSummary.vue | 56 +++++++++ .../{CharacterTab.vue => BuildTab.vue} | 108 +++++------------- .../characterSheetTabs/JournalTab.vue | 60 ++++++++++ app/package-lock.json | 2 +- app/package.json | 2 +- 8 files changed, 160 insertions(+), 87 deletions(-) create mode 100644 app/imports/ui/creature/character/CreatureSummary.vue rename app/imports/ui/creature/character/characterSheetTabs/{CharacterTab.vue => BuildTab.vue} (79%) create mode 100644 app/imports/ui/creature/character/characterSheetTabs/JournalTab.vue diff --git a/app/imports/ui/creature/CreatureFormDialog.vue b/app/imports/ui/creature/CreatureFormDialog.vue index 7f680da9..9a80adce 100644 --- a/app/imports/ui/creature/CreatureFormDialog.vue +++ b/app/imports/ui/creature/CreatureFormDialog.vue @@ -1,5 +1,5 @@ diff --git a/app/imports/ui/properties/forms/NoteForm.vue b/app/imports/ui/properties/forms/NoteForm.vue index a328de80..470c9280 100644 --- a/app/imports/ui/properties/forms/NoteForm.vue +++ b/app/imports/ui/properties/forms/NoteForm.vue @@ -35,6 +35,12 @@ :value="model.tags" @change="change('tags', ...arguments)" /> + + + diff --git a/app/imports/ui/properties/forms/ProficiencyForm.vue b/app/imports/ui/properties/forms/ProficiencyForm.vue index 41961c69..604553bc 100644 --- a/app/imports/ui/properties/forms/ProficiencyForm.vue +++ b/app/imports/ui/properties/forms/ProficiencyForm.vue @@ -37,6 +37,12 @@ :value="model.tags" @change="change('tags', ...arguments)" /> + + + diff --git a/app/imports/ui/properties/forms/ResourcesForm.vue b/app/imports/ui/properties/forms/ResourcesForm.vue index 886ba8c4..5c3e92d9 100644 --- a/app/imports/ui/properties/forms/ResourcesForm.vue +++ b/app/imports/ui/properties/forms/ResourcesForm.vue @@ -24,35 +24,33 @@ @push="({path, value, ack}) => $emit('push', {path: ['itemsConsumed', ...path], value, ack})" @pull="({path, ack}) => $emit('pull', {path: ['itemsConsumed', ...path], ack})" /> -
- - - - - Add Resource - - - Add Ammo - - - -
+ + + + + Add Resource + + + Add Ammo + + + diff --git a/app/imports/ui/properties/forms/RollForm.vue b/app/imports/ui/properties/forms/RollForm.vue index 0355018f..803217e3 100644 --- a/app/imports/ui/properties/forms/RollForm.vue +++ b/app/imports/ui/properties/forms/RollForm.vue @@ -35,6 +35,10 @@ $emit('change', {path: ['roll', ...path], value, ack})" /> + + + + + + + diff --git a/app/imports/ui/properties/forms/SlotFillerForm.vue b/app/imports/ui/properties/forms/SlotFillerForm.vue index d0f84567..5ea5ee44 100644 --- a/app/imports/ui/properties/forms/SlotFillerForm.vue +++ b/app/imports/ui/properties/forms/SlotFillerForm.vue @@ -1,20 +1,37 @@ diff --git a/app/imports/ui/properties/forms/SlotForm.vue b/app/imports/ui/properties/forms/SlotForm.vue index df857437..394808e7 100644 --- a/app/imports/ui/properties/forms/SlotForm.vue +++ b/app/imports/ui/properties/forms/SlotForm.vue @@ -157,38 +157,43 @@ $emit('change', {path: ['description', ...path], value, ack})" /> - -
- + + + + + +
+ + +
+ - -
- -
+
+
diff --git a/app/imports/ui/properties/forms/SpellForm.vue b/app/imports/ui/properties/forms/SpellForm.vue index 7fafb173..88f609d4 100644 --- a/app/imports/ui/properties/forms/SpellForm.vue +++ b/app/imports/ui/properties/forms/SpellForm.vue @@ -238,7 +238,7 @@ $emit('change', {path: ['description', ...path], value, ack})" /> - + + @@ -291,6 +292,11 @@ @change="change('reset', ...arguments)" /> + + + + + + + + + diff --git a/app/imports/ui/properties/forms/ToggleForm.vue b/app/imports/ui/properties/forms/ToggleForm.vue index a10de795..abbff445 100644 --- a/app/imports/ui/properties/forms/ToggleForm.vue +++ b/app/imports/ui/properties/forms/ToggleForm.vue @@ -84,6 +84,13 @@ :value="model.tags" @change="change('tags', ...arguments)" /> + + + + diff --git a/app/imports/ui/properties/forms/shared/propertyFormIndex.js b/app/imports/ui/properties/forms/shared/propertyFormIndex.js index 2e28b01c..09627057 100644 --- a/app/imports/ui/properties/forms/shared/propertyFormIndex.js +++ b/app/imports/ui/properties/forms/shared/propertyFormIndex.js @@ -1,6 +1,5 @@ const ActionForm = () => import('/imports/ui/properties/forms/ActionForm.vue'); const AdjustmentForm = () => import('/imports/ui/properties/forms/AdjustmentForm.vue'); -const AttackForm = () => import('/imports/ui/properties/forms/AttackForm.vue'); const AttributeForm = () => import('/imports/ui/properties/forms/AttributeForm.vue'); const BuffForm = () => import('/imports/ui/properties/forms/BuffForm.vue'); const BranchForm = () => import('/imports/ui/properties/forms/BranchForm.vue'); @@ -28,7 +27,6 @@ const ToggleForm = () => import('/imports/ui/properties/forms/ToggleForm.vue'); export default { action: ActionForm, adjustment: AdjustmentForm, - attack: AttackForm, attribute: AttributeForm, buff: BuffForm, branch: BranchForm, diff --git a/app/imports/ui/properties/forms/shared/propertyFormMixin.js b/app/imports/ui/properties/forms/shared/propertyFormMixin.js index e9eed2f4..172db58f 100644 --- a/app/imports/ui/properties/forms/shared/propertyFormMixin.js +++ b/app/imports/ui/properties/forms/shared/propertyFormMixin.js @@ -1,10 +1,13 @@ import ComputedField from '/imports/ui/properties/forms/shared/ComputedField.vue'; import InlineComputationField from '/imports/ui/properties/forms/shared/InlineComputationField.vue'; +import FormSection, { FormSections } from '/imports/ui/properties/forms/shared/FormSection.vue'; export default { components: { ComputedField, InlineComputationField, + FormSection, + FormSections, }, props: { model: { diff --git a/app/imports/ui/properties/viewers/SlotViewer.vue b/app/imports/ui/properties/viewers/SlotViewer.vue index bdd07cd5..2c5bb3f6 100644 --- a/app/imports/ui/properties/viewers/SlotViewer.vue +++ b/app/imports/ui/properties/viewers/SlotViewer.vue @@ -39,18 +39,28 @@ + + + + mdi-plus + Fill Slot + + - - From 9cc4186171b7e51681b398d06b5f40afde72f5b3 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 21 Jun 2022 11:00:50 +0200 Subject: [PATCH 30/56] Reduced data load in slot fill dialog --- app/imports/server/publications/library.js | 64 ++++++++++--------- .../server/publications/slotFillers.js | 22 +++++-- .../ui/creature/slots/SlotFillDialog.vue | 26 ++++---- .../library/LibraryNodeExpansionContent.vue | 3 + 4 files changed, 65 insertions(+), 50 deletions(-) diff --git a/app/imports/server/publications/library.js b/app/imports/server/publications/library.js index 10553aab..778d08a8 100644 --- a/app/imports/server/publications/library.js +++ b/app/imports/server/publications/library.js @@ -3,6 +3,39 @@ import Libraries from '/imports/api/library/Libraries.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import { assertViewPermission, assertDocViewPermission } from '/imports/api/sharing/sharingPermissions.js'; +const LIBRARY_NODE_TREE_FIELDS = { + _id: 1, + name: 1, + type: 1, + icon: 1, + color: 1, + order: 1, + parent: 1, + ancestors: 1, + // Effect + operation: 1, + targetTags: 1, + stats: 1, + // Item + quantity: 1, + plural: 1, + equipped: 1, + // Branch + branchType: 1, + // Damage: + damageType: 1, + stat: 1, + amount: 1, + // Class level + level: 1, + // Proficiency + value: 1, + // Reference + cache: 1, +} + +export { LIBRARY_NODE_TREE_FIELDS }; + Meteor.publish('libraries', function(){ this.autorun(function (){ let userId = this.userId; @@ -64,36 +97,7 @@ Meteor.publish('libraryNodes', function(libraryId){ 'ancestors.id': libraryId, }, { sort: { order: 1 }, - fields: { - _id: 1, - name: 1, - type: 1, - icon: 1, - color: 1, - order: 1, - parent: 1, - ancestors: 1, - // Effect - operation: 1, - targetTags: 1, - stats: 1, - // Item - quantity: 1, - plural: 1, - equipped: 1, - // Branch - branchType: 1, - // Damage: - damageType: 1, - stat: 1, - amount: 1, - // Class level - level: 1, - // Proficiency - value: 1, - // Reference - cache: 1, - } + fields: LIBRARY_NODE_TREE_FIELDS, }), ]; }); diff --git a/app/imports/server/publications/slotFillers.js b/app/imports/server/publications/slotFillers.js index c5b3397f..3dd6d141 100644 --- a/app/imports/server/publications/slotFillers.js +++ b/app/imports/server/publications/slotFillers.js @@ -3,6 +3,13 @@ import Libraries from '/imports/api/library/Libraries.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import getSlotFillFilter from '/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js' +import { LIBRARY_NODE_TREE_FIELDS } from '/imports/server/publications/library.js'; + +const FIELDS = { + ...LIBRARY_NODE_TREE_FIELDS, + slotFillerCondition: 1, + tags: 1, +} Meteor.publish('slotFillers', function(slotId, searchTerm){ if (searchTerm) check(searchTerm, String); @@ -50,7 +57,8 @@ Meteor.publish('slotFillers', function(slotId, searchTerm){ options = { // relevant documents have a higher score. fields: { - _score: { $meta: 'textScore' } + _score: { $meta: 'textScore' }, + ...FIELDS, }, sort: { // `score` property specified in the projection fields above. @@ -61,10 +69,13 @@ Meteor.publish('slotFillers', function(slotId, searchTerm){ } } else { delete filter.$text - options = {sort: { - name: 1, - order: 1, - }}; + options = { + sort: { + name: 1, + order: 1, + }, + fields: FIELDS, + }; } options.limit = limit; @@ -72,7 +83,6 @@ Meteor.publish('slotFillers', function(slotId, searchTerm){ self.setData('countAll', LibraryNodes.find(filter).count()); }); self.autorun(function () { - Meteor._sleepForMs(1000); return [LibraryNodes.find(filter, options), libraries]; }); }); diff --git a/app/imports/ui/creature/slots/SlotFillDialog.vue b/app/imports/ui/creature/slots/SlotFillDialog.vue index 0b63870f..497b0401 100644 --- a/app/imports/ui/creature/slots/SlotFillDialog.vue +++ b/app/imports/ui/creature/slots/SlotFillDialog.vue @@ -27,20 +27,18 @@ />

{{ slotPropertyTypeName }} with tags: - - + +

Date: Tue, 21 Jun 2022 11:08:45 +0200 Subject: [PATCH 31/56] Iterated on class UI --- app/imports/api/properties/Classes.js | 93 ++++++-- app/imports/ui/properties/forms/ClassForm.vue | 222 ++++++++++++++++++ .../forms/shared/propertyFormIndex.js | 3 +- .../ui/properties/viewers/ClassViewer.vue | 91 +++++++ .../ui/properties/viewers/SlotViewer.vue | 15 +- .../viewers/shared/propertyViewerIndex.js | 3 +- 6 files changed, 405 insertions(+), 22 deletions(-) create mode 100644 app/imports/ui/properties/forms/ClassForm.vue create mode 100644 app/imports/ui/properties/viewers/ClassViewer.vue diff --git a/app/imports/api/properties/Classes.js b/app/imports/api/properties/Classes.js index ee631246..e6e6471f 100644 --- a/app/imports/api/properties/Classes.js +++ b/app/imports/api/properties/Classes.js @@ -1,34 +1,95 @@ import SimpleSchema from 'simpl-schema'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js'; -import { SlotSchema, ComputedOnlySlotSchema } from './Slots.js'; // Classes are like slots, except they only take class levels and enforce that // lower levels are taken before higher levels let ClassSchema = createPropertySchema({ + name: { + type: String, + optional: true, + max: STORAGE_LIMITS.name, + }, + description: { + type: 'inlineCalculationFieldToCompute', + optional: true, + }, // Only `classLevel`s with the same variable name can fill the class variableName: { type: String, optional: true, max: STORAGE_LIMITS.variableName, }, -}).extend(SlotSchema); + slotTags: { + type: Array, + defaultValue: [], + maxCount: STORAGE_LIMITS.tagCount, + }, + 'slotTags.$': { + type: String, + max: STORAGE_LIMITS.tagLength, + }, + extraTags: { + type: Array, + defaultValue: [], + maxCount: STORAGE_LIMITS.extraTagsCount, + }, + 'extraTags.$': { + type: Object, + }, + 'extraTags.$._id': { + type: String, + regEx: SimpleSchema.RegEx.Id, + autoValue(){ + if (!this.isSet) return Random.id(); + } + }, + 'extraTags.$.operation': { + type: String, + allowedValues: ['OR', 'NOT'], + defaultValue: 'OR', + }, + 'extraTags.$.tags': { + type: Array, + defaultValue: [], + maxCount: STORAGE_LIMITS.tagCount, + }, + 'extraTags.$.tags.$': { + type: String, + max: STORAGE_LIMITS.tagLength, + }, + slotCondition: { + type: 'fieldToCompute', + optional: true, + }, +}); const ComputedOnlyClassSchema = createPropertySchema({ - level: { - type: SimpleSchema.Integer, - optional: true, - removeBeforeCompute: true, - }, - missingLevels: { - type: Array, - optional: true, - removeBeforeCompute: true, - }, - 'missingLevels.$': { - type: SimpleSchema.Integer, - }, - }).extend(ComputedOnlySlotSchema); + // Computed fields + description: { + type: 'computedOnlyInlineCalculationField', + optional: true, + }, + slotCondition: { + type: 'computedOnlyField', + optional: true, + }, + + // Denormalised fields + level: { + type: SimpleSchema.Integer, + optional: true, + removeBeforeCompute: true, + }, + missingLevels: { + type: Array, + optional: true, + removeBeforeCompute: true, + }, + 'missingLevels.$': { + type: SimpleSchema.Integer, + }, +}); const ComputedClassSchema = new SimpleSchema() .extend(ClassSchema) diff --git a/app/imports/ui/properties/forms/ClassForm.vue b/app/imports/ui/properties/forms/ClassForm.vue new file mode 100644 index 00000000..50003919 --- /dev/null +++ b/app/imports/ui/properties/forms/ClassForm.vue @@ -0,0 +1,222 @@ + + + diff --git a/app/imports/ui/properties/forms/shared/propertyFormIndex.js b/app/imports/ui/properties/forms/shared/propertyFormIndex.js index 09627057..1687a2cb 100644 --- a/app/imports/ui/properties/forms/shared/propertyFormIndex.js +++ b/app/imports/ui/properties/forms/shared/propertyFormIndex.js @@ -3,6 +3,7 @@ const AdjustmentForm = () => import('/imports/ui/properties/forms/AdjustmentForm const AttributeForm = () => import('/imports/ui/properties/forms/AttributeForm.vue'); const BuffForm = () => import('/imports/ui/properties/forms/BuffForm.vue'); const BranchForm = () => import('/imports/ui/properties/forms/BranchForm.vue'); +const ClassForm = () => import('/imports/ui/properties/forms/ClassForm.vue'); const ClassLevelForm = () => import('/imports/ui/properties/forms/ClassLevelForm.vue'); const ConstantForm = () => import('/imports/ui/properties/forms/ConstantForm.vue'); const ContainerForm = () => import('/imports/ui/properties/forms/ContainerForm.vue'); @@ -32,8 +33,8 @@ export default { branch: BranchForm, constant: ConstantForm, container: ContainerForm, + class: ClassForm, classLevel: ClassLevelForm, - class: SlotForm, damage: DamageForm, damageMultiplier: DamageMultiplierForm, effect: EffectForm, diff --git a/app/imports/ui/properties/viewers/ClassViewer.vue b/app/imports/ui/properties/viewers/ClassViewer.vue new file mode 100644 index 00000000..26e4ffbd --- /dev/null +++ b/app/imports/ui/properties/viewers/ClassViewer.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/app/imports/ui/properties/viewers/SlotViewer.vue b/app/imports/ui/properties/viewers/SlotViewer.vue index 2c5bb3f6..36e432f1 100644 --- a/app/imports/ui/properties/viewers/SlotViewer.vue +++ b/app/imports/ui/properties/viewers/SlotViewer.vue @@ -16,7 +16,7 @@ /> - mdi-plus + + mdi-plus + Fill Slot @@ -68,9 +70,14 @@ } export default { - mixins: [propertyViewerMixin], components: { FillSlotButton, + }, + mixins: [propertyViewerMixin], + inject: { + context: { + default: {}, + }, }, computed: { slotTypeName(){ diff --git a/app/imports/ui/properties/viewers/shared/propertyViewerIndex.js b/app/imports/ui/properties/viewers/shared/propertyViewerIndex.js index 8845fac6..1df889ee 100644 --- a/app/imports/ui/properties/viewers/shared/propertyViewerIndex.js +++ b/app/imports/ui/properties/viewers/shared/propertyViewerIndex.js @@ -4,6 +4,7 @@ const AttributeViewer = () => import ('/imports/ui/properties/viewers/AttributeV const BuffViewer = () => import ('/imports/ui/properties/viewers/BuffViewer.vue'); const BranchViewer = () => import ('/imports/ui/properties/viewers/BranchViewer.vue'); const ContainerViewer = () => import ('/imports/ui/properties/viewers/ContainerViewer.vue'); +const ClassViewer = () => import ('/imports/ui/properties/viewers/ClassViewer.vue'); const ClassLevelViewer = () => import ('/imports/ui/properties/viewers/ClassLevelViewer.vue'); const ConstantViewer = () => import ('/imports/ui/properties/viewers/ConstantViewer.vue'); const DamageViewer = () => import ('/imports/ui/properties/viewers/DamageViewer.vue'); @@ -31,7 +32,7 @@ export default { buff: BuffViewer, branch: BranchViewer, container: ContainerViewer, - class: SlotViewer, + class: ClassViewer, classLevel: ClassLevelViewer, constant: ConstantViewer, damage: DamageViewer, From b484a27637e004ca4bce5a387261a6cde2ccc5c9 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 23 Jun 2022 08:39:15 +0200 Subject: [PATCH 32/56] iterated on class form to match new schema --- app/imports/ui/properties/forms/ClassForm.vue | 55 +++---------------- 1 file changed, 9 insertions(+), 46 deletions(-) diff --git a/app/imports/ui/properties/forms/ClassForm.vue b/app/imports/ui/properties/forms/ClassForm.vue index 50003919..b97e6b3b 100644 --- a/app/imports/ui/properties/forms/ClassForm.vue +++ b/app/imports/ui/properties/forms/ClassForm.vue @@ -22,7 +22,7 @@ @@ -43,7 +43,7 @@ - - - - - Test Slot - - - - + -
- - -
diff --git a/app/imports/ui/properties/treeNodeViews/treeNodeViewIndex.js b/app/imports/ui/properties/treeNodeViews/treeNodeViewIndex.js index 26d52ca0..1f9772e8 100644 --- a/app/imports/ui/properties/treeNodeViews/treeNodeViewIndex.js +++ b/app/imports/ui/properties/treeNodeViews/treeNodeViewIndex.js @@ -7,6 +7,7 @@ import EffectTreeNode from '/imports/ui/properties/treeNodeViews/EffectTreeNode. import ClassLevelTreeNode from '/imports/ui/properties/treeNodeViews/ClassLevelTreeNode.vue'; import ProficiencyTreeNode from '/imports/ui/properties/treeNodeViews/ProficiencyTreeNode.vue'; import ReferenceTreeNode from '/imports/ui/properties/treeNodeViews/ReferenceTreeNode.vue'; +import SavingThrowTreeNode from '/imports/ui/properties/treeNodeViews/SavingThrowTreeNode.vue'; export default { default: DefaultTreeNode, @@ -18,4 +19,5 @@ export default { item: ItemTreeNode, proficiency: ProficiencyTreeNode, reference: ReferenceTreeNode, + savingThrow: SavingThrowTreeNode, } From 292388dead31517932f39aa8ccf187d6aa9f448a Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 29 Jun 2022 15:35:12 +0200 Subject: [PATCH 37/56] Iterated on class UI --- app/imports/ui/properties/forms/ClassForm.vue | 136 +++++++++--------- .../ui/properties/viewers/ClassViewer.vue | 1 + 2 files changed, 69 insertions(+), 68 deletions(-) diff --git a/app/imports/ui/properties/forms/ClassForm.vue b/app/imports/ui/properties/forms/ClassForm.vue index b97e6b3b..d301b750 100644 --- a/app/imports/ui/properties/forms/ClassForm.vue +++ b/app/imports/ui/properties/forms/ClassForm.vue @@ -28,73 +28,6 @@ /> - - - - mdi-plus - - - - - -
- - - - mdi-delete - -
-
- - + + + + mdi-plus + + + + + +
+ + + + mdi-delete + +
+
+ +
diff --git a/app/imports/ui/properties/viewers/ClassViewer.vue b/app/imports/ui/properties/viewers/ClassViewer.vue index 26e4ffbd..44322a52 100644 --- a/app/imports/ui/properties/viewers/ClassViewer.vue +++ b/app/imports/ui/properties/viewers/ClassViewer.vue @@ -11,6 +11,7 @@ :value="model.slotCondition && (model.slotCondition.value || model.slotCondition.calculation)" /> From 1a71c2cfa7feed3a82d4ccbe192221d8e7b0c391 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 4 Jul 2022 13:55:41 +0200 Subject: [PATCH 38/56] Began implementing class level up UI --- .../methods/getSlotFillFilter.js | 29 +- app/imports/server/publications/library.js | 1 + .../server/publications/slotFillers.js | 59 +++ .../ui/creature/slots/LevelUpDialog.vue | 406 ++++++++++++++++++ .../ui/dialogStack/DialogComponentIndex.js | 2 + .../ui/properties/viewers/ClassViewer.vue | 32 +- 6 files changed, 513 insertions(+), 16 deletions(-) create mode 100644 app/imports/ui/creature/slots/LevelUpDialog.vue diff --git a/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js b/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js index 1bba9421..177225b0 100644 --- a/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js +++ b/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js @@ -15,9 +15,30 @@ export default function getSlotFillFilter({slot, libraryIds}){ slotFillerType: slot.slotType, }] }); + } else if (slot.type === 'class') { + filter.$and.push({ + $or: [{ + type: 'classLevel', + },{ + type: 'slotFiller', + slotFillerType: 'classLevel', + }] + }); + filter.variableName = slot.variableName; + + // Only search for levels the class needs + const levels = []; + if (slot.missingLevels && slot.missingLevels.length) { + levels.push(...slot.missingLevels); + } else if (slot.level) { + levels.push(slot.level); + } + if (levels.length) { + filter.level = {$or: levels}; + } } let tagsOr = []; - let tagsNor = []; + let tagsNin = []; if (slot.slotTags && slot.slotTags.length){ tagsOr.push({tags: {$all: slot.slotTags}}); } @@ -27,15 +48,15 @@ export default function getSlotFillFilter({slot, libraryIds}){ if (extra.operation === 'OR'){ tagsOr.push({tags: {$all: extra.tags}}); } else if (extra.operation === 'NOT'){ - tagsNor.push({tags: {$all: extra.tags}}); + tagsNin.push(...extra.tags); } }); } if (tagsOr.length){ filter.$and.push({$or: tagsOr}); } - if (tagsNor.length){ - filter.$and.push({$nor: tagsNor}); + if (tagsNin.length){ + filter.$and.push({$nin: tagsNin}); } if (!filter.$and.length){ delete filter.$and; diff --git a/app/imports/server/publications/library.js b/app/imports/server/publications/library.js index f1d04175..00a45a5b 100644 --- a/app/imports/server/publications/library.js +++ b/app/imports/server/publications/library.js @@ -28,6 +28,7 @@ const LIBRARY_NODE_TREE_FIELDS = { amount: 1, // Class level level: 1, + variableName: 1, // Proficiency value: 1, // Reference diff --git a/app/imports/server/publications/slotFillers.js b/app/imports/server/publications/slotFillers.js index 3dd6d141..e97fa20f 100644 --- a/app/imports/server/publications/slotFillers.js +++ b/app/imports/server/publications/slotFillers.js @@ -88,3 +88,62 @@ Meteor.publish('slotFillers', function(slotId, searchTerm){ }); }); }); + +Meteor.publish('classFillers', function(classId){ + let self = this; + if (!classId) return []; + + this.autorun(function (){ + let userId = this.userId; + if (!userId) { + return []; + } + // Get the class + let classProp = CreatureProperties.findOne(classId); + if (!classProp){ + return []; + } + + // Get all the ids of libraries the user can access + const user = Meteor.users.findOne(userId, { + fields: {subscribedLibraries: 1} + }); + const subs = user && user.subscribedLibraries || []; + let libraries = Libraries.find({ + $or: [ + {owner: userId}, + {writers: userId}, + {readers: userId}, + {_id: {$in: subs}}, + ] + }, { + fields: {_id: 1, name: 1}, + }); + let libraryIds = libraries.map(lib => lib._id); + + // Build a filter for nodes in those libraries that match the slot + let filter = getSlotFillFilter({slot: classProp, libraryIds}); + + this.autorun(function(){ + // Get the limit of the documents the user can fetch + var limit = self.data('limit') || 50; + check(limit, Number); + + let options = { + sort: { + name: 1, + order: 1, + }, + fields: FIELDS, + limit, + }; + + self.autorun(function () { + self.setData('countAll', LibraryNodes.find(filter).count()); + }); + self.autorun(function () { + return [LibraryNodes.find(filter, options), libraries]; + }); + }); + }); +}); diff --git a/app/imports/ui/creature/slots/LevelUpDialog.vue b/app/imports/ui/creature/slots/LevelUpDialog.vue new file mode 100644 index 00000000..4eba1043 --- /dev/null +++ b/app/imports/ui/creature/slots/LevelUpDialog.vue @@ -0,0 +1,406 @@ + + + + + diff --git a/app/imports/ui/dialogStack/DialogComponentIndex.js b/app/imports/ui/dialogStack/DialogComponentIndex.js index 4f0f96e0..8fb87bc7 100644 --- a/app/imports/ui/dialogStack/DialogComponentIndex.js +++ b/app/imports/ui/dialogStack/DialogComponentIndex.js @@ -10,6 +10,7 @@ const DeleteUserAccountDialog = () => import('/imports/ui/user/DeleteUserAccount const ExperienceInsertDialog = () => import( '/imports/ui/creature/experiences/ExperienceInsertDialog.vue'); const ExperienceListDialog = () => import( '/imports/ui/creature/experiences/ExperienceListDialog.vue'); const InviteDialog = () => import('/imports/ui/user/InviteDialog.vue'); +const LevelUpDialog = () => import('/imports/ui/creature/slots/LevelUpDialog.vue'); const LibraryCreationDialog = () => import('/imports/ui/library/LibraryCreationDialog.vue'); const LibraryEditDialog = () => import('/imports/ui/library/LibraryEditDialog.vue'); const LibraryNodeCreationDialog = () => import('/imports/ui/library/LibraryNodeCreationDialog.vue'); @@ -36,6 +37,7 @@ export default { ExperienceInsertDialog, ExperienceListDialog, InviteDialog, + LevelUpDialog, LibraryCreationDialog, LibraryEditDialog, LibraryNodeCreationDialog, diff --git a/app/imports/ui/properties/viewers/ClassViewer.vue b/app/imports/ui/properties/viewers/ClassViewer.vue index 44322a52..d474faec 100644 --- a/app/imports/ui/properties/viewers/ClassViewer.vue +++ b/app/imports/ui/properties/viewers/ClassViewer.vue @@ -47,24 +47,20 @@ :cols="{cols: 12}" > mdi-plus - Get Missing Levels - - - - mdi-plus - - Level Up + + From b8a03245ea5baf0a02851bbe01c43f37ad24c7db Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 5 Jul 2022 15:40:55 +0200 Subject: [PATCH 39/56] Level up dialog now working --- .../methods/getSlotFillFilter.js | 10 +++------- app/imports/server/publications/library.js | 2 ++ .../ui/creature/slots/LevelUpDialog.vue | 9 +-------- .../ui/properties/viewers/ClassViewer.vue | 19 ++++++++++++++++--- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js b/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js index 177225b0..21df0bdb 100644 --- a/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js +++ b/app/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js @@ -27,14 +27,10 @@ export default function getSlotFillFilter({slot, libraryIds}){ filter.variableName = slot.variableName; // Only search for levels the class needs - const levels = []; if (slot.missingLevels && slot.missingLevels.length) { - levels.push(...slot.missingLevels); - } else if (slot.level) { - levels.push(slot.level); - } - if (levels.length) { - filter.level = {$or: levels}; + filter.level = {$in: slot.missingLevels}; + } else { + filter.level = (slot.level || 0) + 1; } } let tagsOr = []; diff --git a/app/imports/server/publications/library.js b/app/imports/server/publications/library.js index 00a45a5b..ebfdc936 100644 --- a/app/imports/server/publications/library.js +++ b/app/imports/server/publications/library.js @@ -12,6 +12,8 @@ const LIBRARY_NODE_TREE_FIELDS = { order: 1, parent: 1, ancestors: 1, + // SlotFillers + slotQuantityFilled: 1, // Effect operation: 1, targetTags: 1, diff --git a/app/imports/ui/creature/slots/LevelUpDialog.vue b/app/imports/ui/creature/slots/LevelUpDialog.vue index 4eba1043..7a09eb1b 100644 --- a/app/imports/ui/creature/slots/LevelUpDialog.vue +++ b/app/imports/ui/creature/slots/LevelUpDialog.vue @@ -26,7 +26,6 @@ :string="model.description" />

- {{ slotPropertyTypeName }} with tags: - import propertyViewerMixin from '/imports/ui/properties/viewers/shared/propertyViewerMixin.js'; +import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js'; export default { mixins: [propertyViewerMixin], @@ -83,13 +84,25 @@ export default { }, methods: { levelUpDialog(){ + let classId = this.model._id; this.$store.commit('pushDialogStack', { component: 'level-up-dialog', elementId: 'level-up-btn', data: { - creatureId: this.creatureId, + creatureId: this.context.creatureId, classId: this.model._id, }, + callback(nodeIds){ + if (!nodeIds || !nodeIds.length) return; + let newPropertyId = insertPropertyFromLibraryNode.call({ + nodeIds, + parentRef: { + 'id': classId, + 'collection': 'creatureProperties', + }, + }); + return `tree-node-${newPropertyId}`; + } }); }, } From 59ef7527b7720f61b7c63ee42be2f6157317baa6 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Sat, 9 Jul 2022 12:53:44 +0200 Subject: [PATCH 40/56] Fixed some errors with character insertion/deletion --- .../creatures/methods/removeCreature.js | 2 ++ .../computation/writeComputation/writeScope.js | 4 ++-- .../ui/creature/character/CharacterSheet.vue | 11 +++++++++++ .../character/characterSheetTabs/BuildTab.vue | 6 ------ .../character/characterSheetTabs/StatsTab.vue | 5 +++-- .../ui/dialogStack/DialogComponentIndex.js | 2 ++ app/imports/ui/pages/CharacterList.vue | 17 +++++++++++++---- 7 files changed, 33 insertions(+), 14 deletions(-) diff --git a/app/imports/api/creature/creatures/methods/removeCreature.js b/app/imports/api/creature/creatures/methods/removeCreature.js index 66eaa0b4..d157f5d7 100644 --- a/app/imports/api/creature/creatures/methods/removeCreature.js +++ b/app/imports/api/creature/creatures/methods/removeCreature.js @@ -3,11 +3,13 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import { assertOwnership } from '/imports/api/creature/creatures/creaturePermissions.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js'; +import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js'; import Experiences from '/imports/api/creature/experience/Experiences.js'; function removeRelatedDocuments(creatureId){ + CreatureVariables.remove({_creatureId: creatureId}); CreatureProperties.remove({'ancestors.id': creatureId}); CreatureLogs.remove({creatureId}); Experiences.remove({creatureId}); diff --git a/app/imports/api/engine/computation/writeComputation/writeScope.js b/app/imports/api/engine/computation/writeComputation/writeScope.js index 04858b8f..1c5bfde3 100644 --- a/app/imports/api/engine/computation/writeComputation/writeScope.js +++ b/app/imports/api/engine/computation/writeComputation/writeScope.js @@ -1,9 +1,9 @@ import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js'; import { EJSON } from 'meteor/ejson'; -import { omitBy } from 'lodash'; export default function writeScope(creatureId, computation) { + if (!creatureId) throw 'creatureId is required'; const scope = computation.scope; const variables = computation.variables || {}; delete variables._id; @@ -50,7 +50,7 @@ export default function writeScope(creatureId, computation) { if ($unset) update.$unset = $unset; CreatureVariables.upsert({_creatureId: creatureId}, update); } - if (computation.creature.dirty) { + if (computation.creature?.dirty) { Creatures.update({_creatureId: creatureId}, {$unset: { dirty: 1 }}); } } diff --git a/app/imports/ui/creature/character/CharacterSheet.vue b/app/imports/ui/creature/character/CharacterSheet.vue index 9edaf0fb..0b4870f0 100644 --- a/app/imports/ui/creature/character/CharacterSheet.vue +++ b/app/imports/ui/creature/character/CharacterSheet.vue @@ -129,6 +129,16 @@ if diff --git a/app/imports/ui/pages/Library.vue b/app/imports/ui/pages/Library.vue index a1f1866a..65a2d18f 100644 --- a/app/imports/ui/pages/Library.vue +++ b/app/imports/ui/pages/Library.vue @@ -10,38 +10,7 @@ xl="8" > - - - - - - - + { meta: { title: 'Library Collection', }, - },{ + }, { + name: 'characterSheet', path: '/character/:id', alias: '/character/:id/:urlName', components: { diff --git a/app/server/main.js b/app/server/main.js index 31140ade..642113e0 100644 --- a/app/server/main.js +++ b/app/server/main.js @@ -15,4 +15,4 @@ import '/imports/migrations/methods/index.js' import '/imports/constants/MAINTENANCE_MODE.js'; import '/imports/api/creature/creatureProperties/methods/index.js'; import '/imports/api/creature/archive/methods/index.js'; - +import '/imports/api/creature/creatures/methods/index.js'; From 0c06f60b7e568f0001edd4882a5b793c43fbdbf2 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 19 Jul 2022 19:25:12 +0200 Subject: [PATCH 44/56] Fixed typo "Transfer Onwership" --- app/imports/ui/sharing/ShareDialog.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/imports/ui/sharing/ShareDialog.vue b/app/imports/ui/sharing/ShareDialog.vue index 728688e6..181b23fe 100644 --- a/app/imports/ui/sharing/ShareDialog.vue +++ b/app/imports/ui/sharing/ShareDialog.vue @@ -92,7 +92,7 @@ mdi-signature - Transfer Onwership + Transfer Ownership From 6f7e742eb9c104f62f743d79de1d77588cfa59f3 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 20 Jul 2022 00:09:58 +0200 Subject: [PATCH 45/56] More of the sheet conforms to library allowances --- .../methods/changeAllowedLibraries.js | 90 ++++++ .../api/creature/creatures/methods/index.js | 1 + .../creatures/methods/insertCreature.js | 8 +- .../server/publications/searchLibraryNodes.js | 28 +- .../server/publications/slotFillers.js | 5 +- app/imports/ui/creature/CreatureForm.vue | 118 ++++++- .../character/CharacterCreationDialog.vue | 2 +- .../creature/character/CharacterSheetFab.vue | 1 + .../AddCreaturePropertyDialog.vue | 296 +++++++++--------- .../CreaturePropertyDialog.vue | 1 + 10 files changed, 377 insertions(+), 173 deletions(-) create mode 100644 app/imports/api/creature/creatures/methods/changeAllowedLibraries.js diff --git a/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js b/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js new file mode 100644 index 00000000..29057f55 --- /dev/null +++ b/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js @@ -0,0 +1,90 @@ +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 SimpleSchema from 'simpl-schema'; +import simpleSchemaMixin from '/imports/api/creature/mixins/simpleSchemaMixin.js'; + +const changeAllowedLibraries = new ValidatedMethod({ + name: 'creatures.changeAllowedLibraries', + mixins: [RateLimiterMixin, simpleSchemaMixin], + schema: new SimpleSchema({ + _id: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + allowedLibraries: { + type: Array, + optional: true, + maxCount: 100, + }, + 'allowedLibraries.$': { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + allowedLibraryCollections: { + type: Array, + optional: true, + maxCount: 100, + }, + 'allowedLibraryCollections.$': { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + }), + rateLimit: { + numRequests: 10, + timeInterval: 5000, + }, + run({_id, allowedLibraries, allowedLibraryCollections}) { + let creature = Creatures.findOne(_id); + assertEditPermission(creature, this.userId); + let $set; + if (allowedLibraries) { + $set = { allowedLibraries } + } + if (allowedLibraryCollections) { + if (!$set) $set = {}; + $set.allowedLibraryCollections = allowedLibraryCollections; + } + if (!$set) return; + Creatures.update(_id, {$set}); + }, +}); + +const toggleAllUserLibraries = new ValidatedMethod({ + name: 'creatures.removeLibraryLimits', + mixins: [RateLimiterMixin, simpleSchemaMixin], + schema: new SimpleSchema({ + _id: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + value: { + type: Boolean, + }, + }), + rateLimit: { + numRequests: 10, + timeInterval: 5000, + }, + run({_id, value}) { + if (value) { + Creatures.update(_id, { + $unset: { + allowedLibraryCollections: 1, + allowedLibraries: 1, + }, + }); + } else { + Creatures.update(_id, { + $set: { + allowedLibraryCollections: [], + allowedLibraries: [], + }, + }); + } + }, +}); + +export {changeAllowedLibraries, toggleAllUserLibraries}; diff --git a/app/imports/api/creature/creatures/methods/index.js b/app/imports/api/creature/creatures/methods/index.js index 42e9c99e..85aefc77 100644 --- a/app/imports/api/creature/creatures/methods/index.js +++ b/app/imports/api/creature/creatures/methods/index.js @@ -2,3 +2,4 @@ import '/imports/api/creature/creatures/methods/insertCreature.js'; import '/imports/api/creature/creatures/methods/removeCreature.js'; import '/imports/api/creature/creatures/methods/restCreature.js'; import '/imports/api/creature/creatures/methods/updateCreature.js'; +import '/imports/api/creature/creatures/methods/changeAllowedLibraries.js'; diff --git a/app/imports/api/creature/creatures/methods/insertCreature.js b/app/imports/api/creature/creatures/methods/insertCreature.js index 210f7b49..da72f6ed 100644 --- a/app/imports/api/creature/creatures/methods/insertCreature.js +++ b/app/imports/api/creature/creatures/methods/insertCreature.js @@ -7,7 +7,7 @@ import defaultCharacterProperties from '/imports/api/creature/creatures/defaultC import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js'; import assertHasCharactersSlots from '/imports/api/creature/creatures/methods/assertHasCharacterSlots.js'; import getSlotFillFilter from '/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js'; -import getUserLibraryIds from '/imports/api/library/getUserLibraryIds.js'; +import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import { insertExperienceForCreature } from '/imports/api/creature/experience/Experiences.js'; import SimpleSchema from 'simpl-schema'; @@ -78,7 +78,7 @@ const insertCreature = new ValidatedMethod({ // If the user only has a single ruleset subscribed, use it by default if (Meteor.isServer) { - insertDefaultRuleset(baseId, userId, rulesetSlot); + insertDefaultRuleset(creatureId, baseId, userId, rulesetSlot); } return creatureId; @@ -86,8 +86,8 @@ const insertCreature = new ValidatedMethod({ }); // If the user only has a single ruleset subscribed, insert it by default -function insertDefaultRuleset(baseId, userId, slot) { - const libraryIds = getUserLibraryIds(userId); +function insertDefaultRuleset(creatureId, baseId, userId, slot) { + const libraryIds = getCreatureLibraryIds(creatureId, userId); const filter = getSlotFillFilter({ slot, libraryIds }); const fillCursor = LibraryNodes.find(filter, { fields: { _id: 1 } }); const numRulesets = fillCursor.count(); diff --git a/app/imports/server/publications/searchLibraryNodes.js b/app/imports/server/publications/searchLibraryNodes.js index ddbbf4ba..cedbc7a8 100644 --- a/app/imports/server/publications/searchLibraryNodes.js +++ b/app/imports/server/publications/searchLibraryNodes.js @@ -1,6 +1,8 @@ import { check } from 'meteor/check'; import Libraries from '/imports/api/library/Libraries.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; +import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds.js'; +import getUserLibraryIds from '/imports/api/library/getUserLibraryIds.js'; import { assertViewPermission } from '/imports/api/sharing/sharingPermissions.js'; Meteor.publish('selectedLibraryNodes', function(selectedNodeIds){ @@ -37,7 +39,7 @@ Meteor.publish('selectedLibraryNodes', function(selectedNodeIds){ })]; }); -Meteor.publish('searchLibraryNodes', function(){ +Meteor.publish('searchLibraryNodes', function(creatureId){ let self = this; this.autorun(function (){ let type = self.data('type'); @@ -49,23 +51,12 @@ Meteor.publish('searchLibraryNodes', function(){ } // Get all the ids of libraries the user can access - const user = Meteor.users.findOne(userId, { - fields: {subscribedLibraries: 1} - }); - if (!user) return []; - - const subs = user.subscribedLibraries || []; - let libraries = Libraries.find({ - $or: [ - {owner: this.userId}, - {writers: this.userId}, - {readers: this.userId}, - {_id: {$in: subs}}, - ] - }, { - fields: {_id: 1, name: 1}, - }); - let libraryIds = libraries.map(lib => lib._id); + let libraryIds; + if (creatureId) { + libraryIds = getCreatureLibraryIds(creatureId, userId) + } else { + libraryIds = getUserLibraryIds(userId) + } // Build a filter for nodes in those libraries that match the type let filter = { @@ -122,6 +113,7 @@ Meteor.publish('searchLibraryNodes', function(){ }); let cursor = LibraryNodes.find(filter, options); + const libraries = Libraries.find({ _id: { $in: libraryIds } }); Mongo.Collection._publishCursor(libraries, self, 'libraries'); diff --git a/app/imports/server/publications/slotFillers.js b/app/imports/server/publications/slotFillers.js index 95a77c6c..ab6e781d 100644 --- a/app/imports/server/publications/slotFillers.js +++ b/app/imports/server/publications/slotFillers.js @@ -3,7 +3,7 @@ import Libraries from '/imports/api/library/Libraries.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import getSlotFillFilter from '/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js' -import getUserLibraryIds from '/imports/api/library/getUserLibraryIds.js'; +import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds.js'; import { LIBRARY_NODE_TREE_FIELDS } from '/imports/server/publications/library.js'; const FIELDS = { @@ -28,7 +28,8 @@ Meteor.publish('slotFillers', function(slotId, searchTerm){ } // Get all the ids of libraries the user can access - const libraryIds = getUserLibraryIds(userId); + const creatureId = slot.ancestors[0].id; + const libraryIds = getCreatureLibraryIds(creatureId, userId); const libraries = Libraries.find({ $or: [ { owner: userId }, diff --git a/app/imports/ui/creature/CreatureForm.vue b/app/imports/ui/creature/CreatureForm.vue index f5506393..b9103ff8 100644 --- a/app/imports/ui/creature/CreatureForm.vue +++ b/app/imports/ui/creature/CreatureForm.vue @@ -33,7 +33,7 @@ @change="(value, ack) => $emit('change', {path: ['avatarPicture'], value, ack})" /> - + --> + + + + +

+ {{ libraryWriteError }} +

+
diff --git a/app/imports/ui/creature/character/CharacterCreationDialog.vue b/app/imports/ui/creature/character/CharacterCreationDialog.vue index 69e33330..568ae394 100644 --- a/app/imports/ui/creature/character/CharacterCreationDialog.vue +++ b/app/imports/ui/creature/character/CharacterCreationDialog.vue @@ -195,7 +195,7 @@ export default { } else { this.$store.commit( 'setTabForCharacterSheet', - {id: creatureId, tab: 4} + {id: creatureId, tab: 5} ); this.$emit('pop', creatureId); defer(() => { diff --git a/app/imports/ui/creature/character/CharacterSheetFab.vue b/app/imports/ui/creature/character/CharacterSheetFab.vue index 4fee5c36..49590d75 100644 --- a/app/imports/ui/creature/character/CharacterSheetFab.vue +++ b/app/imports/ui/creature/character/CharacterSheetFab.vue @@ -170,6 +170,7 @@ data: { parentDoc: forcedType ? undefined : parent, forcedType, + creatureId: this.creatureId, }, callback(result){ if (!result){ diff --git a/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue b/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue index 133d713b..944c7642 100644 --- a/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue +++ b/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue @@ -171,160 +171,166 @@ diff --git a/app/imports/ui/creature/creatureProperties/Breadcrumbs.vue b/app/imports/ui/creature/creatureProperties/Breadcrumbs.vue index 2cd94af0..abc790c6 100644 --- a/app/imports/ui/creature/creatureProperties/Breadcrumbs.vue +++ b/app/imports/ui/creature/creatureProperties/Breadcrumbs.vue @@ -3,9 +3,16 @@ class="breadcrumbs layout align-center wrap" :class="{'no-icons': noIcons}" > + + + mdi-account + +