Fixed adding creatures from libraries -> tabletops
This commit is contained in:
@@ -8,6 +8,7 @@ import LibraryNodes from '/imports/api/library/LibraryNodes';
|
||||
import { getFilter, renewDocIds } from '/imports/api/parenting/parentingFunctions';
|
||||
import { reifyNodeReferences, storeLibraryNodeReferences } from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
|
||||
|
||||
const addCreaturesFromLibraryToTabletop = new ValidatedMethod({
|
||||
|
||||
@@ -58,14 +59,25 @@ const addCreaturesFromLibraryToTabletop = new ValidatedMethod({
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the creature
|
||||
const creatureId = Creatures.insert({
|
||||
...creatureNode,
|
||||
_id: Random.id(),
|
||||
type: 'monster',
|
||||
tabletopId,
|
||||
owner: this.userId,
|
||||
readers: [],
|
||||
writers: [this.userId],
|
||||
public: false,
|
||||
dirty: true,
|
||||
settings: {},
|
||||
});
|
||||
|
||||
// Insert the creature variables
|
||||
CreatureVariables.insert({
|
||||
_creatureId: creatureId,
|
||||
});
|
||||
|
||||
insertSubProperties(creatureNode, creatureId);
|
||||
}
|
||||
},
|
||||
@@ -98,7 +110,7 @@ function insertSubProperties(node, creatureId: string) {
|
||||
|
||||
// Insert the creature properties
|
||||
// @ts-expect-error Batch insert not defined
|
||||
CreatureProperties.batchInsert(nodes);
|
||||
if (nodes.length) CreatureProperties.batchInsert(nodes);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
</div>
|
||||
</v-layout>
|
||||
<div class="text-caption text-no-wrap text-truncate">
|
||||
{{ libraryNames[libraryNode.ancestors[0].id ] }}
|
||||
{{ libraryNames[libraryNode.root.id ] }}
|
||||
</div>
|
||||
</v-layout>
|
||||
<div
|
||||
@@ -225,31 +225,6 @@ export default {
|
||||
name: 'context',
|
||||
include: ['creatureId'],
|
||||
},
|
||||
computed: {
|
||||
tagsSearched() {
|
||||
let or = [];
|
||||
let not = [];
|
||||
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') {
|
||||
or.push(extras.tags);
|
||||
} else if (extras.operation === 'NOT') {
|
||||
not.push(extras.tags);
|
||||
}
|
||||
}
|
||||
});
|
||||
return { or, not };
|
||||
},
|
||||
slotPropertyTypeName() {
|
||||
if (!this.model) return;
|
||||
if (!this.model.slotType) return 'Property';
|
||||
let propName = getPropertyName(this.model.slotType);
|
||||
return propName;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
activeCount(val) {
|
||||
// Still loading fillers
|
||||
@@ -291,7 +266,8 @@ export default {
|
||||
)
|
||||
},
|
||||
insertCustomFiller() {
|
||||
if (!this.model) return;
|
||||
//TODO
|
||||
return;
|
||||
const prop = getDefaultSlotFiller(this.model);
|
||||
const parentRef = { id: this.slotId, collection: 'creatureProperties' };
|
||||
const order = this.model.order + 0.5;
|
||||
@@ -337,30 +313,12 @@ export default {
|
||||
meteor: {
|
||||
$subscribe: {
|
||||
'creatureTemplates'() {
|
||||
return [this.slotId || this.dummySlot?._id, this.searchValue || undefined, !!this.dummySlot]
|
||||
},
|
||||
'selectedFillers'() {
|
||||
return [this.slotId || this.dummySlot?._id, this.selectedNodeIds, !!this.dummySlot]
|
||||
return [this.searchValue || undefined]
|
||||
},
|
||||
},
|
||||
searchLoading() {
|
||||
return !!this.searchValue && !this.$subReady.creatureTemplates;
|
||||
},
|
||||
model() {
|
||||
if (this.slotId) {
|
||||
return CreatureProperties.findOne(this.slotId);
|
||||
} else if (this.dummySlot) {
|
||||
let model = clone(this.dummySlot)
|
||||
if (!model.quantityExpected) model.quantityExpected = {};
|
||||
model.quantityExpected.value = +model.quantityExpected.calculation;
|
||||
model.spaceLeft = model.quantityExpected.value;
|
||||
return model;
|
||||
}
|
||||
},
|
||||
variables() {
|
||||
if (!this.creatureId) return {};
|
||||
return CreatureVariables.findOne({ _creatureId: this.creatureId }) || {};
|
||||
},
|
||||
currentLimit() {
|
||||
return this._subs['creatureTemplates'].data('limit') || 50;
|
||||
},
|
||||
@@ -376,45 +334,6 @@ export default {
|
||||
if (!filterString) return;
|
||||
return EJSON.parse(filterString);
|
||||
},
|
||||
alreadyAdded() {
|
||||
let added = new Set();
|
||||
if (!this.model.unique) return added;
|
||||
let ancestorId;
|
||||
if (this.model.unique === 'uniqueInSlot') {
|
||||
ancestorId = this.model._id;
|
||||
} else if (this.model.unique === 'uniqueInCreature') {
|
||||
ancestorId = this.creatureId;
|
||||
}
|
||||
CreatureProperties.find({
|
||||
'ancestors.id': ancestorId,
|
||||
libraryNodeId: { $exists: true },
|
||||
removed: { $ne: true },
|
||||
}, {
|
||||
fields: { libraryNodeId: 1 },
|
||||
}).forEach(prop => {
|
||||
added.add(prop.libraryNodeId);
|
||||
});
|
||||
return added;
|
||||
},
|
||||
totalQuantitySelected() {
|
||||
let quantitySelected = 0;
|
||||
LibraryNodes.find({
|
||||
_id: { $in: this.selectedNodeIds }
|
||||
}, {
|
||||
fields: { slotQuantityFilled: 1 },
|
||||
}).forEach(node => {
|
||||
if (Number.isFinite(node.slotQuantityFilled)) {
|
||||
quantitySelected += node.slotQuantityFilled;
|
||||
} else {
|
||||
quantitySelected += 1;
|
||||
}
|
||||
});
|
||||
return quantitySelected;
|
||||
},
|
||||
spaceLeft() {
|
||||
if (!this.model.quantityExpected || this.model.quantityExpected.value === 0) return undefined;
|
||||
return this.model.spaceLeft - this.totalQuantitySelected;
|
||||
},
|
||||
libraryNames() {
|
||||
let names = {};
|
||||
Libraries.find().forEach(lib => names[lib._id] = lib.name)
|
||||
|
||||
@@ -159,11 +159,6 @@ export default {
|
||||
}
|
||||
},
|
||||
meteor: {
|
||||
$subscribe: {
|
||||
'tabletop'() {
|
||||
return [this.model._id];
|
||||
},
|
||||
},
|
||||
creatures(){
|
||||
return Creatures.find({ tabletopId: this.model._id });
|
||||
},
|
||||
|
||||
140
app/imports/server/publications/creatureTemplates.js
Normal file
140
app/imports/server/publications/creatureTemplates.js
Normal file
@@ -0,0 +1,140 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Libraries from '/imports/api/library/Libraries';
|
||||
import LibraryNodes from '/imports/api/library/LibraryNodes';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import getSlotFillFilter from '/imports/api/creature/creatureProperties/methods/getSlotFillFilter'
|
||||
import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds';
|
||||
import { LIBRARY_NODE_TREE_FIELDS } from '/imports/server/publications/library';
|
||||
import escapeRegex from '/imports/api/utility/escapeRegex';
|
||||
import getUserLibraryIds from '/imports/api/library/getUserLibraryIds';
|
||||
|
||||
// Publish docs the user has already selected so they don't disappear when searching
|
||||
Meteor.publish('selectedCreatureTemplates', function (nodeIds) {
|
||||
let autorun = this.autorun;
|
||||
autorun(function () {
|
||||
// TODO
|
||||
return [];
|
||||
let userId = this.userId;
|
||||
if (!userId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get all the ids of libraries the user can access
|
||||
const creatureId = slot.root.id;
|
||||
const libraryIds = getCreatureLibraryIds(creatureId, userId);
|
||||
const libraries = Libraries.find({
|
||||
$or: [
|
||||
{ owner: userId },
|
||||
{ writers: userId },
|
||||
{ readers: userId },
|
||||
{ _id: { $in: libraryIds }, public: true },
|
||||
]
|
||||
}, {
|
||||
sort: { name: 1 }
|
||||
});
|
||||
|
||||
let filter = { _id: { $in: nodeIds } };
|
||||
// Get the limit of the documents the user can fetch
|
||||
let options = {
|
||||
sort: {
|
||||
name: 1,
|
||||
order: 1,
|
||||
},
|
||||
limit: 100,
|
||||
fields: LIBRARY_NODE_TREE_FIELDS,
|
||||
};
|
||||
autorun(function () {
|
||||
return [
|
||||
LibraryNodes.find(filter, options),
|
||||
libraries
|
||||
];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Meteor.publish('creatureTemplates', function (searchTerm) {
|
||||
if (searchTerm) check(searchTerm, String);
|
||||
|
||||
let self = this;
|
||||
this.autorun(function () {
|
||||
let userId = this.userId;
|
||||
if (!userId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get all the ids of libraries the user can access
|
||||
const userLibIds = getUserLibraryIds(userId);
|
||||
const libraries = Libraries.find({
|
||||
$or: [
|
||||
{ owner: userId },
|
||||
{ writers: userId },
|
||||
{ readers: userId },
|
||||
{ _id: { $in: userLibIds }, public: true },
|
||||
]
|
||||
}, {
|
||||
sort: { name: 1 }
|
||||
});
|
||||
|
||||
const libraryIds = libraries.map(lib => lib._id);
|
||||
|
||||
this.autorun(function () {
|
||||
// Build a filter for nodes in those libraries
|
||||
const filter = {
|
||||
'root.id': { $in: libraryIds },
|
||||
type: 'creature',
|
||||
removed: { $ne: true },
|
||||
}
|
||||
|
||||
// Get the limit of the documents the user can fetch
|
||||
var limit = self.data('limit') || 50;
|
||||
check(limit, Number);
|
||||
|
||||
let options = undefined;
|
||||
if (searchTerm) {
|
||||
if (!filter.$and) filter.$and = [];
|
||||
filter.$and.push({
|
||||
$or: [
|
||||
{ name: { $regex: escapeRegex(searchTerm), '$options': 'i' } },
|
||||
{ libraryTags: searchTerm }
|
||||
]
|
||||
});
|
||||
//filter.$text = { $search: searchTerm };
|
||||
options = {
|
||||
// relevant documents have a higher score.
|
||||
fields: {
|
||||
//_score: { $meta: 'textScore' },
|
||||
...LIBRARY_NODE_TREE_FIELDS,
|
||||
},
|
||||
sort: {
|
||||
// `score` property specified in the projection fields above.
|
||||
//_score: { $meta: 'textScore' },
|
||||
name: 1,
|
||||
order: 1,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//delete filter.$text
|
||||
delete filter.name
|
||||
options = {
|
||||
sort: {
|
||||
name: 1,
|
||||
order: 1,
|
||||
},
|
||||
fields: LIBRARY_NODE_TREE_FIELDS,
|
||||
};
|
||||
}
|
||||
options.limit = limit;
|
||||
|
||||
self.autorun(function () {
|
||||
self.setData('countAll', LibraryNodes.find(filter).count());
|
||||
self.setData('libraryNodeFilter', EJSON.stringify(filter));
|
||||
});
|
||||
self.autorun(function () {
|
||||
return [
|
||||
LibraryNodes.find(filter, options),
|
||||
libraries
|
||||
];
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import '/imports/server/publications/publicationRateLimit';
|
||||
import '/imports/server/publications/characterList';
|
||||
import '/imports/server/publications/creatureTemplates';
|
||||
import '/imports/server/publications/library';
|
||||
import '/imports/server/publications/singleCharacter';
|
||||
import '/imports/server/publications/experiences';
|
||||
|
||||
Reference in New Issue
Block a user