From e8158ba531abc711e4d3f7831336492c8df8111d Mon Sep 17 00:00:00 2001
From: Thaum Rystra <9525416+ThaumRystra@users.noreply.github.com>
Date: Mon, 28 Oct 2024 14:26:48 +0200
Subject: [PATCH] Iterate on action engine and tree data store migration
---
.../creature/actions/input/CastSpellInput.vue | 24 +----
.../CreaturePropertyDialog.vue | 2 +-
.../ui/creature/slots/LevelUpDialog.vue | 9 +-
.../client/ui/library/LibraryEditDialog.vue | 3 +-
.../client/ui/log/TabletopLogContent.vue | 87 +++++++++++++++----
.../ui/properties/InsertPropertyDialog.vue | 5 +-
.../ui/properties/viewers/SkillViewer.vue | 7 +-
.../client/ui/tabletop/TabletopActionCard.vue | 15 ++--
.../client/ui/tabletop/TabletopBuffCard.vue | 29 +++----
.../client/ui/tabletop/TabletopComponent.vue | 5 +-
app/imports/server/publications/library.js | 9 +-
.../server/publications/searchLibraryNodes.js | 10 ++-
.../server/rest/apiPublications/creature.js | 47 ----------
13 files changed, 124 insertions(+), 128 deletions(-)
diff --git a/app/imports/client/ui/creature/actions/input/CastSpellInput.vue b/app/imports/client/ui/creature/actions/input/CastSpellInput.vue
index f94d4190..81d096fa 100644
--- a/app/imports/client/ui/creature/actions/input/CastSpellInput.vue
+++ b/app/imports/client/ui/creature/actions/input/CastSpellInput.vue
@@ -145,15 +145,6 @@
-
- Cast
-
@@ -186,18 +177,10 @@ export default {
type: String,
required: true,
},
- slotId: {
- type: String,
- default: undefined,
- },
value: {
type: Object,
required: true,
},
- spellId: {
- type: String,
- default: undefined,
- },
},
data() {
return {
@@ -258,7 +241,7 @@ export default {
} else {
const newSlot = find(
CreatureProperties.find({
- 'ancestors.id': this.creatureId,
+ ...getFilter.descendantsOfRoot(this.creatureId),
...slotFilter
}, {
sort: { 'spellSlotLevel.value': 1, order: 1 },
@@ -339,9 +322,6 @@ export default {
);
}
},
- cast() {
- this.$emit('continue');
- }
},
meteor: {
spells() {
@@ -379,7 +359,7 @@ export default {
},
spellSlots() {
return CreatureProperties.find({
- 'ancestors.id': this.creatureId,
+ ...getFilter.descendantsOfRoot(this.creatureId),
...slotFilter
}, {
sort: { 'spellSlotLevel.value': 1, order: 1 },
diff --git a/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue b/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue
index f21c4041..a31ac8f6 100644
--- a/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue
+++ b/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue
@@ -87,7 +87,7 @@ import { getPropertyName } from '/imports/constants/PROPERTIES';
import PropertyForm from '/imports/client/ui/properties/PropertyForm.vue';
import getPropertyTitle from '/imports/client/ui/properties/shared/getPropertyTitle';
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
-import { get, findLast } from 'lodash';
+import { get } from 'lodash';
import equipItem from '/imports/api/creature/creatureProperties/methods/equipItem';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue';
import insertProperty from '/imports/api/creature/creatureProperties/methods/insertProperty';
diff --git a/app/imports/client/ui/creature/slots/LevelUpDialog.vue b/app/imports/client/ui/creature/slots/LevelUpDialog.vue
index 73d6cb4a..58c05eb1 100644
--- a/app/imports/client/ui/creature/slots/LevelUpDialog.vue
+++ b/app/imports/client/ui/creature/slots/LevelUpDialog.vue
@@ -86,7 +86,7 @@
- {{ libraryNames[libraryNode.ancestors[0].id ] }}
+ {{ libraryNames[libraryNode.root.id ] }}
-
- {{ content.name }}
-
-
+
mdi-chevron-right
+
+
+
+ {{ creature.name && creature.name[0] || '?' }}
+
+
+
+ v-for="(content, contentIndex) in contentGroup.content"
+ :key="contentIndex"
+ class="content-line"
+ >
+
+ {{ content.name }}
+
+
+
+
diff --git a/app/imports/client/ui/properties/InsertPropertyDialog.vue b/app/imports/client/ui/properties/InsertPropertyDialog.vue
index b3ad859e..78904e89 100644
--- a/app/imports/client/ui/properties/InsertPropertyDialog.vue
+++ b/app/imports/client/ui/properties/InsertPropertyDialog.vue
@@ -206,7 +206,6 @@ import getThemeColor from '/imports/client/ui/utility/getThemeColor';
import PropertySelector from '/imports/client/ui/properties/shared/PropertySelector.vue';
import {snackbar} from '/imports/client/ui/components/snackbars/SnackbarQueue';
import PropertyForm from '/imports/client/ui/properties/PropertyForm.vue';
-import SimpleSchema from 'simpl-schema';
export default {
components: {
@@ -372,9 +371,9 @@ export default {
_searchResult: true
},{
sort: {
- 'ancestors.0.id': 1,
name: 1,
- order: 1,
+ type: 1,
+ left: 1,
},
});
},
diff --git a/app/imports/client/ui/properties/viewers/SkillViewer.vue b/app/imports/client/ui/properties/viewers/SkillViewer.vue
index a9604589..f3525800 100644
--- a/app/imports/client/ui/properties/viewers/SkillViewer.vue
+++ b/app/imports/client/ui/properties/viewers/SkillViewer.vue
@@ -123,6 +123,7 @@ import SkillProficiency from '/imports/client/ui/properties/components/skills/Sk
import getProficiencyIcon from '/imports/client/ui/utility/getProficiencyIcon';
import sortEffects from '/imports/client/ui/utility/sortEffects';
import PropertyTargetTags from '/imports/client/ui/properties/viewers/shared/PropertyTargetTags.vue';
+import { getFilter } from '/imports/api/parenting/parentingFunctions';
export default {
components: {
@@ -201,12 +202,12 @@ export default {
let ability = this.model.ability;
if (!creatureId || !ability) return;
let abilityProp = CreatureProperties.findOne({
+ ...getFilter.descendantsOfRoot(creatureId),
variableName: ability,
type: 'attribute',
removed: { $ne: true },
inactive: { $ne: true },
overridden: { $ne: true },
- 'ancestors.id': creatureId,
});
if (!abilityProp) return;
return {
@@ -215,16 +216,16 @@ export default {
operation: 'base',
amount: { value: abilityProp.modifier },
stats: [this.model.variableName],
- ancestors: abilityProp.ancestors,
+ root: abilityProp.root,
}
},
proficiencyBonus() {
return CreatureProperties.findOne({
+ ...getFilter.descendantsOfRoot(this.context.creatureId),
variableName: 'proficiencyBonus',
overridden: { $ne: true },
removed: { $ne: true },
inactive: { $ne: true },
- 'ancestors.id': this.context.creatureId,
})?.value;
},
},
diff --git a/app/imports/client/ui/tabletop/TabletopActionCard.vue b/app/imports/client/ui/tabletop/TabletopActionCard.vue
index ff27ab92..5d63b0bd 100644
--- a/app/imports/client/ui/tabletop/TabletopActionCard.vue
+++ b/app/imports/client/ui/tabletop/TabletopActionCard.vue
@@ -109,6 +109,7 @@ import TreeNodeList from '/imports/client/ui/components/tree/TreeNodeList.vue';
import { docsToForest } from '/imports/api/parenting/parentingFunctions';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
import { some } from 'lodash';
+import { getFilter } from '/imports/api/parenting/parentingFunctions';
export default {
components: {
@@ -184,9 +185,9 @@ export default {
},
meteor: {
children() {
- const indicesOfTerminatingProps = [];
+ const excludedRanges = [];
const decendants = CreatureProperties.find({
- 'ancestors.id': this.model._id,
+ ...getFilter.descendants(this.model),
'removed': { $ne: true },
}, {
sort: {left: 1}
@@ -194,9 +195,9 @@ export default {
// Get all the props we don't want to show the decendants of and
// where they might appear in the ancestor list
if (prop.type === 'buff' || prop.type === 'folder') {
- indicesOfTerminatingProps.push({
- id: prop._id,
- ancestorIndex: prop.ancestors.length,
+ excludedRanges.push({
+ left: prop.left,
+ right: prop.right,
});
}
return prop;
@@ -204,8 +205,8 @@ export default {
// Filter out folders entirely
if (prop.type === 'folder') return false;
// Filter out decendants of terminating props
- return !some(indicesOfTerminatingProps, buffIndex => {
- return prop.ancestors[buffIndex.ancestorIndex]?.id === buffIndex.id;
+ return !some(excludedRanges, range => {
+ return prop.left > range.left && prop.right < range.right;
});
});
return docsToForest(decendants);
diff --git a/app/imports/client/ui/tabletop/TabletopBuffCard.vue b/app/imports/client/ui/tabletop/TabletopBuffCard.vue
index 2d425ddb..0de0ce1d 100644
--- a/app/imports/client/ui/tabletop/TabletopBuffCard.vue
+++ b/app/imports/client/ui/tabletop/TabletopBuffCard.vue
@@ -64,6 +64,7 @@ import TreeNodeList from '/imports/client/ui/components/tree/TreeNodeList.vue';
import { docsToForest } from '/imports/api/parenting/parentingFunctions';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
import { some } from 'lodash';
+import { getFilter } from '/imports/api/parenting/parentingFunctions';
export default {
components: {
@@ -137,31 +138,29 @@ export default {
},
meteor: {
children() {
- const indicesOfTerminatingProps = [];
- const decendants = CreatureProperties.find({
- 'ancestors.id': this.model._id,
+ const excludedRanges = [];
+ const descendants = CreatureProperties.find({
+ ...getFilter.descendants(this.model),
'removed': { $ne: true },
}, {
sort: {left: 1}
}).map(prop => {
- // Get all the props we don't want to show the decendants of and
- // where they might appear in the ancestor list
- if (prop.type === 'buff' || prop.type === 'folder') {
- indicesOfTerminatingProps.push({
- id: prop._id,
- ancestorIndex: prop.ancestors.length,
- });
- }
+ // Get all the props we don't want to show the descendants of and what range they cover in
+ // the tree
+ excludedRanges.push({
+ left: prop.left,
+ right: prop.right,
+ });
return prop;
}).filter(prop => {
// Filter out folders entirely
if (prop.type === 'folder') return false;
- // Filter out decendants of terminating props
- return !some(indicesOfTerminatingProps, buffIndex => {
- return prop.ancestors[buffIndex.ancestorIndex]?.id === buffIndex.id;
+ // Filter out descendants of terminating props
+ return !some(excludedRanges, range => {
+ return prop.left > range.left && prop.right < range.right;
});
});
- return docsToForest(decendants);
+ return docsToForest(descendants);
},
},
methods: {
diff --git a/app/imports/client/ui/tabletop/TabletopComponent.vue b/app/imports/client/ui/tabletop/TabletopComponent.vue
index e1381500..b821d88e 100644
--- a/app/imports/client/ui/tabletop/TabletopComponent.vue
+++ b/app/imports/client/ui/tabletop/TabletopComponent.vue
@@ -109,12 +109,11 @@ import { assertEditPermission } from '/imports/api/creature/creatures/creaturePe
import SelectedCreatureBar from '/imports/client/ui/tabletop/selectedCreatureBar/SelectedCreatureBar.vue';
import addCreaturesFromLibraryToTabletop from '/imports/api/tabletop/methods/addCreaturesFromLibraryToTabletop';
import removeCreatureFromTabletop from '/imports/api/tabletop/methods/removeCreatureFromTabletop';
+import { getFilter } from '/imports/api/parenting/parentingFunctions';
const getProperties = function (creatureId, selector = {}) {
return CreatureProperties.find({
- 'ancestors.id': {
- $eq: creatureId,
- },
+ ...getFilter.descendantsOfRoot(creatureId),
inactive: { $ne: true },
removed: { $ne: true },
overridden: { $ne: true },
diff --git a/app/imports/server/publications/library.js b/app/imports/server/publications/library.js
index 2466617c..5482866f 100644
--- a/app/imports/server/publications/library.js
+++ b/app/imports/server/publications/library.js
@@ -4,6 +4,7 @@ import LibraryCollections from '/imports/api/library/LibraryCollections';
import LibraryNodes from '/imports/api/library/LibraryNodes';
import { assertViewPermission, assertDocViewPermission } from '/imports/api/sharing/sharingPermissions';
import { union } from 'lodash';
+import { getFilter } from '/imports/api/parenting/parentingFunctions';
const LIBRARY_NODE_TREE_FIELDS = {
_id: 1,
@@ -284,7 +285,7 @@ Meteor.publish('softRemovedLibraryNodes', function (libraryId) {
}
return [
LibraryNodes.find({
- 'ancestors.0.id': libraryId,
+ ...getFilter.descendantsOfRoot(libraryId),
removed: true,
removedWith: { $exists: false },
}, {
@@ -296,8 +297,8 @@ Meteor.publish('softRemovedLibraryNodes', function (libraryId) {
Meteor.publish('descendantLibraryNodes', function (nodeId) {
let node = LibraryNodes.findOne(nodeId);
- let libraryId = node?.ancestors[0]?.id;
- if (!libraryId) return [];
+ let libraryId = node?.root.id;
+ if (!libraryId || !node) return [];
this.autorun(function () {
let userId = this.userId;
let library = Libraries.findOne(libraryId);
@@ -307,7 +308,7 @@ Meteor.publish('descendantLibraryNodes', function (nodeId) {
}
return [
LibraryNodes.find({
- 'ancestors.id': nodeId,
+ ...getFilter.descendants(node),
}, {
sort: { left: 1 },
}),
diff --git a/app/imports/server/publications/searchLibraryNodes.js b/app/imports/server/publications/searchLibraryNodes.js
index 44edb214..72c017df 100644
--- a/app/imports/server/publications/searchLibraryNodes.js
+++ b/app/imports/server/publications/searchLibraryNodes.js
@@ -5,6 +5,7 @@ import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds';
import getUserLibraryIds from '/imports/api/library/getUserLibraryIds';
import { assertViewPermission } from '/imports/api/sharing/sharingPermissions';
import escapeRegex from '/imports/api/utility/escapeRegex';
+import { getFilter } from '/imports/api/parenting/parentingFunctions';
Meteor.publish('selectedLibraryNodes', function (selectedNodeIds) {
check(selectedNodeIds, Array);
@@ -13,10 +14,12 @@ Meteor.publish('selectedLibraryNodes', function (selectedNodeIds) {
selectedNodeIds = selectedNodeIds.slice(0, 20);
}
let libraryViewPermissions = {};
+ const nodes = [];
// Check view permissions of all libraries
for (let id of selectedNodeIds) {
let node = LibraryNodes.findOne(id);
if (!node) continue;
+ nodes.push(node);
let libraryId = node.ancestors[0].id;
if (libraryViewPermissions[id]) {
continue;
@@ -27,6 +30,9 @@ Meteor.publish('selectedLibraryNodes', function (selectedNodeIds) {
readers: 1,
writers: 1,
public: 1,
+ root: 1,
+ left: 1,
+ right: 1,
}
});
assertViewPermission(library, this.userId);
@@ -37,7 +43,7 @@ Meteor.publish('selectedLibraryNodes', function (selectedNodeIds) {
return [LibraryNodes.find({
$or: [
{ _id: { $in: selectedNodeIds } },
- { 'ancestors.id': { $in: selectedNodeIds } },
+ { ...getFilter.descendantsOfAll(nodes) },
],
})];
});
@@ -63,7 +69,7 @@ Meteor.publish('searchLibraryNodes', function (creatureId) {
// Build a filter for nodes in those libraries that match the type
let filter = {
- 'ancestors.id': { $in: libraryIds },
+ ...getFilter.descendantsOfAllRoots(libraryIds),
removed: { $ne: true },
searchable: true //library nodes must opt-in
};
diff --git a/app/imports/server/rest/apiPublications/creature.js b/app/imports/server/rest/apiPublications/creature.js
index 9f0fcc5e..f25abc82 100644
--- a/app/imports/server/rest/apiPublications/creature.js
+++ b/app/imports/server/rest/apiPublications/creature.js
@@ -53,50 +53,3 @@ JsonRoutes.add('get', 'api/creature/:id', function (req, res) {
});
});
-
-/*
-Meteor.publish('api-creature', function (creatureId) {
- try {
- new SimpleSchema({
- creatureId: {
- type: String,
- regEx: SimpleSchema.RegEx.Id,
- },
- }).validate({ creatureId });
- } catch (e) {
- console.error(e)
- this.error(e);
- return;
- }
- const userId = this.userId;
- const creatureCursor = Creatures.find({
- _id: creatureId,
- });
- const creature = creatureCursor.fetch()[0];
- try {
- assertViewPermission(creature, userId)
- } catch (e) {
- console.error(e)
- this.error(e);
- return;
- }
- if (creature.computeVersion !== VERSION) {
- try {
- computeCreature(creatureId)
- } catch (e) {
- console.error(e)
- }
- }
- return [
- creatureCursor,
- CreatureProperties.find({
- 'ancestors.id': creatureId,
- }),
- CreatureVariables.find({
- _creatureId: creatureId,
- }),
- ];
-}, {
- url: 'api/creature/:0'
-});
-*/