Compare commits

...

24 Commits

Author SHA1 Message Date
Stefan Zermatten
ee1b876259 Bumped version 2022-11-29 14:53:23 +02:00
Stefan Zermatten
12fbca5c78 Merge branch 'version-2-dev' into version-2 2022-11-29 14:53:01 +02:00
Stefan Zermatten
da6fb55ca0 Fixed automated tab navs. going to the wrong tab 2022-11-29 14:52:22 +02:00
Stefan Zermatten
8551e318c2 Demoted features tab back in tab order 2022-11-29 14:35:27 +02:00
Stefan Zermatten
f175cffab8 Bumped version 2022-11-29 14:27:53 +02:00
Stefan Zermatten
2bca582af6 Merge branch 'version-2-dev' into version-2 2022-11-29 14:26:59 +02:00
Stefan Zermatten
5815c7ca34 Padded character list to reveal add folder button
It was hiding behind FAB
2022-11-29 14:10:28 +02:00
Stefan Zermatten
c237162475 Fixed sidebar party closing on route change 2022-11-29 14:05:24 +02:00
Stefan Zermatten
e87772c2a3 Fixed folder groupStats behaviour when !groupStats 2022-11-29 12:06:27 +02:00
Stefan Zermatten
704314a7eb Udpated npm packages 2022-11-29 11:48:28 +02:00
Stefan Zermatten
7ffd0bf61d Fixed menus in dialogs in firefox
Also improved look of scrollbars incl. dark mode
2022-11-29 11:48:20 +02:00
Stefan Zermatten
69b3ba781d Disabled tabletop routing for now 2022-11-28 23:41:10 +02:00
Stefan Zermatten
bf8eb52a96 bumped number of writers limit from 20 to 32 2022-11-28 16:54:21 +02:00
Stefan Zermatten
684d672028 Removed column layout hacks
Fixes drag fallbacks not being in front of cards
Might fix flashy shit on ios
2022-11-28 15:40:47 +02:00
Stefan Zermatten
fb98544ae1 Fixed drag and drop on Firefox 2022-11-28 15:39:47 +02:00
Stefan Zermatten
ec8b9c209c fixed rests on actions with undefined usesUsed 2022-11-28 14:50:41 +02:00
Stefan Zermatten
bee90a7a80 Fixed rests on attributes with undefined damage 2022-11-28 14:49:38 +02:00
Stefan Zermatten
5ad0de9eb7 Bumped version 2022-11-25 16:36:44 +02:00
Stefan Zermatten
0b377fcb71 Attributes show their children in stats cards 2022-11-25 16:27:18 +02:00
Stefan Zermatten
1f26fbf00e Iterated on stat grouping cards
adde slots, spell lists, children of slot fillers
hid properties in most places
spell slots in correct order
2022-11-25 13:25:38 +02:00
Stefan Zermatten
bb1e9624ad Fixed hit dice missing on stats tab 2022-11-25 12:14:47 +02:00
Stefan Zermatten
bda446858e Fixed spell tab btn not hiding correctly on mobile 2022-11-24 15:04:35 +02:00
Stefan Zermatten
e19e91f7e0 Fixed broken $attackRoll always returning 0 2022-11-24 14:51:05 +02:00
Stefan Zermatten
bac9fc98dd Fixed order of stats tab, unhid sneaky folders 2022-11-24 14:48:58 +02:00
37 changed files with 568 additions and 230 deletions

View File

@@ -83,13 +83,13 @@ export function resetProperties(creatureId, resetFilter, actionContext) {
const attributeFilter = {
...filter,
type: 'attribute',
damage: { $ne: 0 },
damage: { $nin: [0, undefined] },
}
CreatureProperties.find(attributeFilter).forEach(prop => {
damagePropertyWork({
prop,
operation: 'increment',
value: -prop.damage,
value: -prop.damage ?? 0,
actionContext,
logFunction(increment) {
actionContext.addLog({
@@ -105,7 +105,7 @@ export function resetProperties(creatureId, resetFilter, actionContext) {
type: {
$in: ['action', 'spell']
},
usesUsed: { $ne: 0 },
usesUsed: { $nin: [0, undefined] },
};
CreatureProperties.find(actionFilter, {
fields: { name: 1, usesUsed: 1 }

View File

@@ -165,7 +165,7 @@ function rollAttack(attack, scope) {
}
scope['$attackDiceRoll'] = { value };
const result = value + attack.value;
scope['$attackRoll'] = { result };
scope['$attackRoll'] = { value: result };
const { criticalHit, criticalMiss } = applyCrits(value, scope);
return { resultPrefix, result, value, criticalHit, criticalMiss };
}

View File

@@ -39,17 +39,6 @@ export default {
.column-layout>div,
.column-layout>span>div {
/*
Table and width set because firefox does not support break-inside: avoid
*/
display: table;
table-layout: fixed;
width: 100%;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
transform: translateX(0);
-webkit-transform: translateX(0);
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
padding: 4px;

View File

@@ -2,8 +2,8 @@
<v-icon
class="handle"
v-bind="$attrs"
@click.stop="() => { }"
@touchstart.native.stop="() => { }"
@click.native="e => { }"
@touchstart.native.stop="e => { }"
@touchend.native="portalEvent"
>
mdi-drag

View File

@@ -218,30 +218,30 @@ export default {
},
methods: {
changeShowTreeTab(value) {
let currentTab = this.$store.getters.tabNameById(this.model._id);
if (!value && currentTab === 'tree') {
this.$store.commit(
'setTabForCharacterSheet',
{ id: this.model._id, tab: 'build' }
);
}
this.$emit('change', {
path: ['settings', 'showTreeTab'],
value: !!value
});
let currentTab = this.$store.getters.tabById(this.model._id);
if (!value && currentTab === 5) {
this.$store.commit(
'setTabForCharacterSheet',
{ id: this.model._id, tab: 4 }
);
}
},
changeHideSpellsTab(value) {
let currentTab = this.$store.getters.tabNameById(this.model._id);
if (!value && currentTab === 'spells') {
this.$store.commit(
'setTabForCharacterSheet',
{ id: this.model._id, tab: 'actions' }
);
}
this.$emit('change', {
path: ['settings', 'hideSpellsTab'],
value: !value
});
let currentTab = this.$store.getters.tabById(this.model._id);
if (!value && currentTab === 3) {
this.$store.commit(
'setTabForCharacterSheet',
{ id: this.model._id, tab: 4 }
);
}
},
allUserLibrariesChange(value, ack) {
toggleAllUserLibraries.call({

View File

@@ -4,7 +4,7 @@
:class="{
'empty': !hasChildren,
}"
:data-id="`build-tree-node-${node._id}`"
:data-id="`tree-node-${node._id}`"
>
<div
class="layout align-center justify-start tree-node-title"

View File

@@ -195,7 +195,7 @@ export default {
} else {
this.$store.commit(
'setTabForCharacterSheet',
{id: creatureId, tab: 5}
{id: creatureId, tab: 'build'}
);
this.$emit('pop', creatureId);
defer(() => {

View File

@@ -47,9 +47,6 @@
<v-tab-item>
<stats-tab :creature-id="creatureId" />
</v-tab-item>
<v-tab-item>
<features-tab :creature-id="creatureId" />
</v-tab-item>
<v-tab-item>
<actions-tab :creature-id="creatureId" />
</v-tab-item>
@@ -59,6 +56,9 @@
<v-tab-item>
<inventory-tab :creature-id="creatureId" />
</v-tab-item>
<v-tab-item>
<features-tab :creature-id="creatureId" />
</v-tab-item>
<v-tab-item>
<character-tab :creature-id="creatureId" />
</v-tab-item>
@@ -96,22 +96,22 @@
<span>Stats</span>
<v-icon>mdi-chart-box</v-icon>
</v-btn>
<v-btn>
<span>Features</span>
<v-icon>mdi-text</v-icon>
</v-btn>
<v-btn>
<span>Actions</span>
<v-icon>mdi-lightning-bolt</v-icon>
</v-btn>
<v-btn>
<span v-if="!creature.settings.hideSpellsTab">Spells</span>
<v-btn v-if="!creature.settings.hideSpellsTab">
<span>Spells</span>
<v-icon>mdi-fire</v-icon>
</v-btn>
<v-btn>
<span>Inventory</span>
<v-icon>mdi-cube</v-icon>
</v-btn>
<v-btn>
<span>Features</span>
<v-icon>mdi-text</v-icon>
</v-btn>
<v-btn>
<span>Journal</span>
<v-icon>mdi-book-open-variant</v-icon>

View File

@@ -101,9 +101,6 @@
<v-tab>
Stats
</v-tab>
<v-tab>
Features
</v-tab>
<v-tab>
Actions
</v-tab>
@@ -113,6 +110,9 @@
<v-tab>
Inventory
</v-tab>
<v-tab>
Features
</v-tab>
<v-tab>
Journal
</v-tab>

View File

@@ -58,8 +58,20 @@ export default {
}},
meteor: {
actions() {
return CreatureProperties.find({
const folderIds = CreatureProperties.find({
'ancestors.id': this.creatureId,
type: 'folder',
groupStats: true,
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: folderIds,
},
type: 'action',
actionType: { $ne: 'event' },
removed: { $ne: true },

View File

@@ -86,7 +86,7 @@
<build-tree-node-list
:children="slotBuildTree"
class="mx-2"
@selected="_id => propertyClicked({_id, prefix: 'build-tree-node-'})"
@selected="_id => propertyClicked({_id, prefix: 'tree-node-'})"
/>
</v-card>
</v-col>

View File

@@ -56,8 +56,20 @@ export default {
},
meteor: {
features() {
return CreatureProperties.find({
const folderIds = CreatureProperties.find({
'ancestors.id': this.creatureId,
type: 'folder',
groupStats: true,
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: folderIds,
},
type: 'feature',
removed: { $ne: true },
inactive: { $ne: true },

View File

@@ -141,9 +141,22 @@ export default {
};
},
meteor: {
containers() {
folderIds() {
return CreatureProperties.find({
'ancestors.id': this.creatureId,
type: 'folder',
groupStats: true,
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
},
containers() {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.folderIds,
},
type: 'container',
removed: { $ne: true },
inactive: { $ne: true },
@@ -166,7 +179,7 @@ export default {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.containerIds
$nin: [...this.containerIds, ...this.folderIds],
},
type: 'container',
removed: { $ne: true },
@@ -179,7 +192,7 @@ export default {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.containerIds
$nin: [...this.containerIds, ...this.folderIds],
},
type: 'item',
equipped: { $ne: true },

View File

@@ -60,8 +60,20 @@ export default {
},
meteor: {
notes(){
return CreatureProperties.find({
const folderIds = CreatureProperties.find({
'ancestors.id': this.creatureId,
type: 'folder',
groupStats: true,
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: folderIds,
},
type: 'note',
removed: {$ne: true},
inactive: {$ne: true},

View File

@@ -10,7 +10,7 @@
@remove="softRemove"
/>
<div
v-if="spellSlots && spellSlots.length || hasSpells"
v-if="hasSpellSlots || hasSpells"
class="spell-slots"
>
<spell-slot-card
@@ -77,9 +77,33 @@ export default {
}
},
meteor: {
spellSlots() {
folderIds() {
return CreatureProperties.find({
'ancestors.id': this.creatureId,
type: 'folder',
groupStats: true,
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
},
hasSpellSlots() {
return !!CreatureProperties.findOne({
'ancestors.id': this.creatureId,
inactive: { $ne: true },
removed: { $ne: true },
overridden: { $ne: true },
level: { $ne: 0 },
type: 'attribute',
attributeType: 'spellSlot',
});
},
spellSlots() {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.folderIds,
},
inactive: { $ne: true },
removed: { $ne: true },
overridden: { $ne: true },
@@ -89,11 +113,16 @@ export default {
{ hideWhenTotalZero: true, total: 0 },
{ hideWhenValueZero: true, value: 0 },
],
}, {
sort: { order: 1 }
});
},
spellLists() {
return CreatureProperties.find({
'ancestors.id': this.creatureId,
'ancestors.id': {
$eq: this.creatureId,
$nin: this.folderIds,
},
type: 'spellList',
removed: { $ne: true },
inactive: { $ne: true },
@@ -113,7 +142,7 @@ export default {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.spellListIds,
$nin: [...this.spellListIds, ...this.folderIds],
},
type: 'spell',
removed: { $ne: true },
@@ -130,7 +159,7 @@ export default {
return CreatureProperties.find({
'ancestors.id': {
$eq: this.creatureId,
$nin: this.spellListIds,
$nin: [...this.spellListIds, ...this.folderIds],
},
type: 'spellList',
removed: { $ne: true },

View File

@@ -161,13 +161,13 @@
</div>
<div
v-if="properties.hitDice && properties.hitDice.length"
v-if="properties.attribute.hitDice && properties.attribute.hitDice.length"
class="hit-dice"
>
<v-card>
<v-list>
<v-subheader>Hit Dice</v-subheader>
<template v-for="(hitDie, index) in hitDice">
<template v-for="(hitDie, index) in properties.attribute.hitDice">
<v-divider
v-if="index !== 0"
:key="hitDie._id + 'divider'"
@@ -427,10 +427,10 @@ const propertyHandlers = {
folder(prop) {
let skipChildren;
let propPath = null;
if (prop.hideStatsGroup) {
return { skipChildren: true}
if (prop.groupStats && prop.hideStatsGroup) {
skipChildren = true;
}
if (prop.tab === 'stats') {
if (prop.groupStats && prop.tab === 'stats') {
propPath = ['folder', prop.location]
}
return { skipChildren, propPath }
@@ -546,7 +546,7 @@ export default {
if (creature.settings.hideUnusedStats) {
filter.hide = { $ne: true };
}
const allProps = CreatureProperties.find(filter, { sort: { order: 1 } });
const allProps = CreatureProperties.find(filter, { sort: { order: -1 } });
const forest = nodeArrayToTree(allProps);
const properties = { folder: {}, attribute: {}, skill: {} };
walkDown(forest, node => {

View File

@@ -1,5 +1,5 @@
<template lang="html">
<v-list-item-content style="min-height: 60px;">
<v-list-item-content :style="dense ? undefined : 'min-height: 60px;'">
<v-list-item-title class="d-flex align-center">
<div
v-if="!renaming"

View File

@@ -1,6 +1,8 @@
<template lang="html">
<v-list
expand
:nav="nav"
:dense="dense"
class="creature-folder-list"
>
<creature-list
@@ -14,7 +16,7 @@
v-for="folder in folders"
:key="folder._id"
v-model="openFolders[folder._id]"
group="folder"
:dense="dense"
>
<template #activator>
<creature-folder-header
@@ -60,6 +62,7 @@ export default {
default: undefined,
},
dense: Boolean,
nav: Boolean,
},
data(){return{
openFolders: {},

View File

@@ -5,10 +5,12 @@
<v-list-item
v-bind="$attrs"
:class="isSelected && 'primary--text v-list-item--active'"
:dense="dense"
v-on="selection ? { click() {$emit('click')} } : {}"
>
<v-list-item-avatar
:color="isSelected ? 'red darken-1' : model.color || 'grey'"
:size="dense ? 30 : undefined"
class="white--text"
style="transition: background 0.3s;"
>

View File

@@ -8,7 +8,7 @@
class="slot-card d-flex flex-column"
@mouseover="hover = true"
@mouseleave="hover = false"
@click="$emit('click')"
@click="fillSlot"
>
<card-highlight
:active="hover"
@@ -28,7 +28,7 @@
<v-btn
icon
color="accent"
@click.stop="$emit('ignore')"
@click.stop="ignoreProp"
>
<v-icon>mdi-close</v-icon>
</v-btn>
@@ -39,6 +39,9 @@
<script lang="js">
import CardHighlight from '/imports/client/ui/components/CardHighlight.vue';
import PropertyDescription from '/imports/client/ui/properties/viewers/shared/PropertyDescription.vue';
import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
import updateCreatureProperty from '/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js';
export default {
components: {
@@ -51,6 +54,9 @@ export default {
isDark: false,
},
},
context: {
default: {},
},
},
props: {
model: {
@@ -72,5 +78,45 @@ export default {
}
}
},
methods: {
fillSlot() {
const slotId = this.model._id;
this.$store.commit('pushDialogStack', {
component: 'slot-fill-dialog',
elementId: `slot-card-${slotId}`,
data: {
slotId,
creatureId: this.context.creatureId,
},
callback(nodeIds){
if (!nodeIds || !nodeIds.length) return;
insertPropertyFromLibraryNode.call({
nodeIds,
parentRef: {
'id': slotId,
'collection': 'creatureProperties',
},
}, error => {
if (error){
console.error(error);
snackbar({text: error.reason || error.message || error.toString()});
}
});
}
});
},
ignoreProp(){
updateCreatureProperty.call({
_id: this.model._id,
path: ['ignored'],
value: true
}, error => {
if (error){
console.error(error);
snackbar({text: error.reason || error.message || error.toString()});
}
});
},
}
}
</script>

View File

@@ -1,5 +1,8 @@
<template>
<column-layout wide-columns class="slots-to-fill">
<column-layout
wide-columns
class="slots-to-fill"
>
<v-fade-transition
group
leave-absolute
@@ -39,7 +42,6 @@ import SlotCard from '/imports/client/ui/creature/slots/SlotCard.vue';
import PointBuyCard from '/imports/client/ui/properties/components/pointBuy/PointBuyCard.vue';
import ColumnLayout from '/imports/client/ui/components/ColumnLayout.vue';
import updateCreatureProperty from '/imports/api/creature/creatureProperties/methods/updateCreatureProperty.js';
import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js';
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
export default {
@@ -64,31 +66,6 @@ export default {
}
});
},
fillSlot(slotId){
this.$store.commit('pushDialogStack', {
component: 'slot-fill-dialog',
elementId: `slot-card-${slotId}`,
data: {
slotId,
creatureId: this.context.creatureId,
},
callback(nodeIds){
if (!nodeIds || !nodeIds.length) return;
insertPropertyFromLibraryNode.call({
nodeIds,
parentRef: {
'id': slotId,
'collection': 'creatureProperties',
},
}, error => {
if (error){
console.error(error);
snackbar({text: error.reason || error.message || error.toString()});
}
});
}
});
},
editPointBuy(_id){
this.$store.commit('pushDialogStack', {
component: 'creature-property-dialog',
@@ -101,10 +78,21 @@ export default {
},
},
meteor: {
slots(){
return CreatureProperties.find({
type: 'propertySlot',
slots() {
const folderIds = CreatureProperties.find({
'ancestors.id': this.context.creatureId,
type: 'folder',
hideStatsGroup: true,
removed: { $ne: true },
inactive: { $ne: true },
}, { fields: { _id: 1 } }).map(folder => folder._id);
return CreatureProperties.find({
'ancestors.id': {
$eq: this.context.creatureId,
$nin: folderIds,
},
type: 'propertySlot',
ignored: { $ne: true },
$and: [
{

View File

@@ -63,21 +63,14 @@
},
watch: {
dialogs(newDialogs) {
let el = document.documentElement;
const el = document.documentElement;
if (newDialogs.length) {
this.top = el.scrollTop;
if (el.scrollHeight > el.clientHeight){
el.style.position = 'fixed';
el.style.top = `${-this.top}px`;
el.style.left = 0;
el.style.right = 0;
el.style.overflowY = 'scroll';
el.style.overflowY = 'hidden';
el.scrollTop = this.top;
}
} else {
el.style.position = null;
el.style.top = null;
el.style.left = null;
el.style.right = null;
el.style.overflowY = null;
el.scrollTop = this.top;
}

View File

@@ -11,7 +11,10 @@
Sign in
</v-btn>
</v-layout>
<v-list>
<v-list
nav
class="links"
>
<v-list-item v-if="signedIn">
<v-list-item-content>
<v-list-item-title>
@@ -138,3 +141,9 @@ export default {
},
};
</script>
<style scoped>
.links .v-list-item:not(:last-child):not(:only-child) {
margin-bottom: 4px;
}
</style>

View File

@@ -4,7 +4,10 @@
style="height: 100%"
>
<v-container>
<v-row justify="center">
<v-row
justify="center"
class="mb-16"
>
<v-col
cols="12"
xl="8"

View File

@@ -15,7 +15,8 @@
:model="prop"
:data-id="prop._id"
@click="$emit('click-property', {_id: prop._id})"
@sub-click="_id => $emit('sub-click', _id)"
@click-property="e => $emit('click-property', e)"
@sub-click="e => $emit('sub-click', e)"
@remove="$emit('remove', prop._id)"
/>
</v-card>
@@ -27,15 +28,15 @@ import CreatureProperties from '/imports/api/creature/creatureProperties/Creatur
import propComponents from '/imports/client/ui/properties/components/folders/propertyComponentIndex.js';
export default {
components: {
...propComponents,
},
props: {
model: {
type: Object,
required: true,
}
},
beforeCreate() {
Object.assign(this.$options.components, propComponents);
},
meteor: {
properties() {
const props = [];
@@ -50,6 +51,7 @@ export default {
deactivatedByAncestor: { $ne: true },
},
{
type: { $ne: 'toggle' },
inactive: { $ne: true }
},
],
@@ -60,7 +62,7 @@ export default {
}, {
sort: { order: 1 },
}).forEach(prop => {
if (this.$options.components[prop.type]) {
if (propComponents[prop.type]) {
props.push(prop);
}
});

View File

@@ -1,44 +1,55 @@
<template>
<div class="attribute">
<ability-list-tile
v-if="model.attributeType === 'ability'"
<div>
<div
class="attribute"
:data-id="dataId"
>
<ability-list-tile
v-if="model.attributeType === 'ability'"
:model="model"
@click="$emit('click')"
/>
<hit-dice-list-tile
v-else-if="model.attributeType === 'hitDice'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
/>
<health-bar
v-else-if="model.attributeType === 'healthBar'"
:model="model"
@change="damageProperty"
@click="$emit('click')"
/>
<spell-slot-list-tile
v-else-if="model.attributeType === 'spellSlot'"
:model="model"
@click="$emit('click')"
/>
<resource-card-content
v-else-if="model.attributeType === 'resource'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<attribute-card-content
v-else-if="model.attributeType !== 'utility'"
class="pointer"
:model="model"
@click="$emit('click')"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<card-highlight :active="hover" />
</div>
<folder-group-children
:model="model"
@click="$emit('click')"
@click-property="e => $emit('click-property', e)"
@sub-click="e => $emit('sub-click', e)"
@remove="e => $emit('remove', e)"
/>
<hit-dice-list-tile
v-else-if="model.attributeType === 'hitDice'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
/>
<health-bar
v-else-if="model.attributeType === 'healthBar'"
:model="model"
@change="damageProperty"
@click="$emit('click')"
/>
<spell-slot-list-tile
v-else-if="model.attributeType === 'spellSlot'"
:model="model"
@click="$emit('click')"
/>
<resource-card-content
v-else-if="model.attributeType === 'resource'"
:model="model"
@click="$emit('click')"
@change="({ type, value }) => damageProperty({type, value: -value})"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<attribute-card-content
v-else-if="model.attributeType !== 'utility'"
class="pointer"
:model="model"
@click="$emit('click')"
@mouseover="hover = true"
@mouseleave="hover = false"
/>
<card-highlight :active="hover" />
</div>
</template>
@@ -50,6 +61,7 @@ import SpellSlotListTile from '/imports/client/ui/properties/components/attribut
import ResourceCardContent from '/imports/client/ui/properties/components/attributes/ResourceCardContent.vue';
import AttributeCardContent from '/imports/client/ui/properties/components/attributes/AttributeCardContent.vue';
import CardHighlight from '/imports/client/ui/components/CardHighlight.vue';
import FolderGroupChildren from '/imports/client/ui/properties/components/folders/folderGroupComponents/FolderGroupChildren.vue';
import damageProperty from '/imports/api/creature/creatureProperties/methods/damageProperty.js';
@@ -62,12 +74,17 @@ export default {
ResourceCardContent,
AttributeCardContent,
CardHighlight,
FolderGroupChildren,
},
props: {
model: {
type: Object,
required: true,
},
dataId: {
type: String,
required: true,
},
},
data() {
return {
@@ -81,6 +98,10 @@ export default {
value: change.value
});
},
log({_id}) {
console.log(...arguments)
this.$emit('click-property', { _id });
}
}
}
</script>

View File

@@ -0,0 +1,66 @@
<template>
<div
v-if="properties && properties.length"
>
<component
:is="prop.type"
v-for="prop in properties"
:key="prop._id"
:model="prop"
:data-id="prop._id"
@click="$emit('click-property', {_id: prop._id})"
@click-property="(e) => $emit('click-property', e)"
@sub-click="(e) => $emit('sub-click', e)"
@remove="$emit('remove', prop._id)"
/>
</div>
</template>
<script lang="js">
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import propComponents from '/imports/client/ui/properties/components/folders/propertyComponentIndex.js';
export default {
props: {
model: {
type: Object,
required: true,
}
},
beforeCreate() {
Object.assign(this.$options.components, propComponents);
},
meteor: {
properties() {
const props = [];
CreatureProperties.find({
'parent.id': this.model._id,
removed: { $ne: true },
overridden: { $ne: true },
$or: [
{
type: 'toggle',
showUI: true,
deactivatedByAncestor: { $ne: true },
},
{
type: { $ne: 'toggle' },
inactive: { $ne: true },
},
],
$nor: [
{ hideWhenTotalZero: true, total: 0 },
{ hideWhenValueZero: true, value: 0 },
],
}, {
sort: { order: 1 },
}).forEach(prop => {
if (propComponents[prop.type]) {
props.push(prop);
}
});
return props;
},
},
}
</script>

View File

@@ -0,0 +1,82 @@
<template>
<build-tree-node-list
:children="slotBuildTree"
class="mx-2"
@selected="_id => $emit('sub-click', _id)"
/>
</template>
<script lang="js">
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import { nodeArrayToTree } from '/imports/api/parenting/nodesToTree.js';
import BuildTreeNodeList from '/imports/client/ui/creature/buildTree/BuildTreeNodeList.vue';
function traverse(tree, callback, parents = []){
tree.forEach(node => {
callback(node, parents);
traverse(node.children, callback, [...parents, node]);
});
}
export default {
components: {
BuildTreeNodeList,
},
props: {
model: {
type: Object,
required: true,
},
},
meteor: {
slotBuildTree() {
const slots = CreatureProperties.find({
$and: [ {
$or: [
{ 'ancestors.id': this.model._id, },
{ '_id': this.model._id, },
],
}, {
$or:
[
{ 'slotCondition.value': { $nin: [false, 0, ''] } },
{ 'slotCondition.value': { $exists: false } },
{ 'slotCondition': { $exists: false } },
],
} ],
type: { $in: ['propertySlot', 'pointBuy'] },
removed: { $ne: true },
inactive: { $ne: true },
}, {
sort: { order: 1 }
});
const slotIds = slots.map(s => s._id);
const slotChildren = CreatureProperties.find({
'parent.id': { $in: slotIds },
removed: { $ne: true },
}, {
sort: { order: 1 },
});
const tree = nodeArrayToTree([
...slots.fetch(),
...slotChildren.fetch()
]);
traverse(tree, (child, parents) => {
const model = child.node;
const isSlotWithSpace = model.type === 'propertySlot' && (
model.spaceLeft > 0 ||
!model.quantityExpected ||
model.quantityExpected.value === 0
);
if (isSlotWithSpace) {
model._canFill = true;
parents.forEach(node => {
node.node._descendantCanFill = true;
});
}
});
return tree;
},
}
}
</script>

View File

@@ -17,16 +17,17 @@ import item from '/imports/client/ui/properties/components/inventory/ItemListTil
import note from '/imports/client/ui/properties/components/persona/NoteCard.vue';
//import pointBuy from '';
//import proficiency from '';
//import propertySlot from '';
import propertySlot from '/imports/client/ui/properties/components/folders/folderGroupComponents/SlotBuildTree.vue';
//import reference from '';
//import roll from '';
//import savingThrow from '';
import skill from '/imports/client/ui/properties/components/skills/SkillListTile.vue';
//import slotFiller from '';
//import spellList from '';
//import spell from '';
import spellList from '/imports/client/ui/properties/components/spells/SpellListCard.vue';
import spell from '/imports/client/ui/properties/components/spells/SpellListTile.vue';
import toggle from '/imports/client/ui/properties/components/toggles/ToggleCard.vue';
//import trigger from '';
import FolderGroupChildren from '/imports/client/ui/properties/components/folders/folderGroupComponents/FolderGroupChildren.vue';
export default {
action,
@@ -43,19 +44,19 @@ export default {
//damageMultiplier,
//effect,
feature,
//folder,
// folder // Like actions, we don't show sub-folders
item,
note,
//pointBuy,
//proficiency,
//propertySlot,
propertySlot,
//reference,
//roll,
//savingThrow,
skill,
//slotFiller,
//spellList,
//spell,
slotFiller: FolderGroupChildren,
spellList,
spell,
toggle,
//trigger,
};

View File

@@ -35,7 +35,7 @@
<v-expand-transition>
<div v-if="model.groupStats">
<smart-switch
label="Hide children from stats tab"
label="Hide children from their default locations"
:value="model.hideStatsGroup"
:error-messages="errors.hideStatsGroup"
@change="change('hideStatsGroup', ...arguments)"

View File

@@ -189,7 +189,9 @@ RouterFactory.configure(router => {
meta: {
title: 'Print Character Sheet',
},
}, {
},
/* Not ready for prime time <3
{
path: '/tabletops',
name: 'tabletops',
component: Tabletops,
@@ -203,7 +205,9 @@ RouterFactory.configure(router => {
rightDrawer: TabletopRightDrawer,
},
beforeEnter: ensureLoggedIn,
}, {
},
*/
{
path: '/friends',
components: {
default: NotImplemented,

View File

@@ -0,0 +1,37 @@
html {
--scrollbarBG: #f0f0f0;
--thumbBG: #cdcdcd;
scrollbar-gutter: stable;
background-color: var(--scrollbarBG);
}
html:has(#app.theme--dark) {
--scrollbarBG: #212121;
--thumbBG: #404040;
}
#app.theme--dark {
--scrollbarBG: #212121;
--thumbBG: #404040;
}
* {
scrollbar-width: thin;
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
}
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background-color: var(--scrollbarBG);
}
::-webkit-scrollbar-thumb {
background-color: var(--thumbBG);
}
::-webkit-scrollbar-corner {
background-color: rgba(0, 0, 0, 0);
}

View File

@@ -1,3 +1,4 @@
import './body.css';
import './cardColors.css';
import './cardTitles.css';
import './centeredInputs.css';

View File

@@ -2,8 +2,8 @@ import Vue from 'vue';
import Vuex from 'vuex';
import dialogStackStore from '/imports/client/ui/dialogStack/dialogStackStore.js';
import Creatures from '/imports/api/creature/creatures/Creatures.js';
const tabs = ['stats', 'features', 'actions', 'spells', 'inventory', 'journal', 'build', 'tree'];
const tabsWithoutSpells = ['stats', 'features', 'actions', 'inventory', 'journal', 'build', 'tree'];
const tabs = ['stats', 'actions', 'spells', 'inventory', 'features', 'journal', 'build', 'tree'];
const tabsWithoutSpells = ['stats', 'actions', 'inventory', 'features', 'journal', 'build', 'tree'];
Vue.use(Vuex);
const store = new Vuex.Store({
@@ -50,6 +50,19 @@ const store = new Vuex.Store({
document.title = value;
},
setTabForCharacterSheet(state, { tab, id }) {
// Convert tab names to tab numbers
if (typeof tab === 'string') {
const creature = Creatures.findOne(id);
if (creature?.settings?.hideSpellsTab) {
tab = tabsWithoutSpells.indexOf(tab);
} else {
tab = tabs.indexOf(tab);
}
if (!(tab > -1)) {
throw 'Could not find requested tab';
}
console.log('resolved: ', tab);
}
Vue.set(state.characterSheetTabs, id, tab);
},
setShowDetailsDialog(state, value) {

View File

@@ -30,7 +30,7 @@ const STORAGE_LIMITS = Object.freeze({
rollCount: 64,
statsToTarget: 64,
tagCount: 64,
writersCount: 20,
writersCount: 32,
libraryCollectionCount: 32,
pointBuyRowsCount: 32,
});

114
app/package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "dicecloud",
"version": "2.0.43",
"version": "2.0.45",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -56,11 +56,11 @@
"dev": true
},
"@babel/runtime": {
"version": "7.20.1",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz",
"integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==",
"version": "7.20.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz",
"integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==",
"requires": {
"regenerator-runtime": "^0.13.10"
"regenerator-runtime": "^0.13.11"
}
},
"@chenfengyuan/vue-countdown": {
@@ -185,14 +185,14 @@
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.43.0.tgz",
"integrity": "sha512-wNPzG+eDR6+hhW4yobEmpR36jrqqQv1vxBq5LJO3fBAktjkvekfr4BRl+3Fn1CM/A+s8/EiGUbOMDoYqWdbtXA==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.44.0.tgz",
"integrity": "sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.43.0",
"@typescript-eslint/type-utils": "5.43.0",
"@typescript-eslint/utils": "5.43.0",
"@typescript-eslint/scope-manager": "5.44.0",
"@typescript-eslint/type-utils": "5.44.0",
"@typescript-eslint/utils": "5.44.0",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
@@ -222,14 +222,14 @@
}
},
"@typescript-eslint/parser": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz",
"integrity": "sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.44.0.tgz",
"integrity": "sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.43.0",
"@typescript-eslint/types": "5.43.0",
"@typescript-eslint/typescript-estree": "5.43.0",
"@typescript-eslint/scope-manager": "5.44.0",
"@typescript-eslint/types": "5.44.0",
"@typescript-eslint/typescript-estree": "5.44.0",
"debug": "^4.3.4"
},
"dependencies": {
@@ -245,23 +245,23 @@
}
},
"@typescript-eslint/scope-manager": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz",
"integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.44.0.tgz",
"integrity": "sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.43.0",
"@typescript-eslint/visitor-keys": "5.43.0"
"@typescript-eslint/types": "5.44.0",
"@typescript-eslint/visitor-keys": "5.44.0"
}
},
"@typescript-eslint/type-utils": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.43.0.tgz",
"integrity": "sha512-K21f+KY2/VvYggLf5Pk4tgBOPs2otTaIHy2zjclo7UZGLyFH86VfUOm5iq+OtDtxq/Zwu2I3ujDBykVW4Xtmtg==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.44.0.tgz",
"integrity": "sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w==",
"dev": true,
"requires": {
"@typescript-eslint/typescript-estree": "5.43.0",
"@typescript-eslint/utils": "5.43.0",
"@typescript-eslint/typescript-estree": "5.44.0",
"@typescript-eslint/utils": "5.44.0",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
@@ -278,19 +278,19 @@
}
},
"@typescript-eslint/types": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz",
"integrity": "sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.44.0.tgz",
"integrity": "sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz",
"integrity": "sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.44.0.tgz",
"integrity": "sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.43.0",
"@typescript-eslint/visitor-keys": "5.43.0",
"@typescript-eslint/types": "5.44.0",
"@typescript-eslint/visitor-keys": "5.44.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -319,16 +319,16 @@
}
},
"@typescript-eslint/utils": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.43.0.tgz",
"integrity": "sha512-8nVpA6yX0sCjf7v/NDfeaOlyaIIqL7OaIGOWSPFqUKK59Gnumd3Wa+2l8oAaYO2lk0sO+SbWFWRSvhu8gLGv4A==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.44.0.tgz",
"integrity": "sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"@types/semver": "^7.3.12",
"@typescript-eslint/scope-manager": "5.43.0",
"@typescript-eslint/types": "5.43.0",
"@typescript-eslint/typescript-estree": "5.43.0",
"@typescript-eslint/scope-manager": "5.44.0",
"@typescript-eslint/types": "5.44.0",
"@typescript-eslint/typescript-estree": "5.44.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0",
"semver": "^7.3.7"
@@ -355,12 +355,12 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz",
"integrity": "sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==",
"version": "5.44.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.44.0.tgz",
"integrity": "sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.43.0",
"@typescript-eslint/types": "5.44.0",
"eslint-visitor-keys": "^3.3.0"
},
"dependencies": {
@@ -530,9 +530,9 @@
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"aws-sdk": {
"version": "2.1258.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1258.0.tgz",
"integrity": "sha512-siqNFXlhJZVN1BizPZebJViFXtTUPgcA+yLfHKl2eC4Ied7kE7spOjZmAzpuiGUTzFagk1oWCaJ1Hit4llIoGg==",
"version": "2.1262.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1262.0.tgz",
"integrity": "sha512-XbaK/XUIxwLEBnHANhJ0RTZtiU288lFRj5FllSihQ5Kb0fibKyW8kJFPsY+NzzDezLH5D3WdGbTKb9fycn5TbA==",
"requires": {
"buffer": "4.9.2",
"events": "1.1.1",
@@ -1575,9 +1575,9 @@
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
},
"ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ=="
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz",
"integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA=="
},
"ignore-styles": {
"version": "5.0.1",
@@ -1850,9 +1850,9 @@
}
},
"marked": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.2.2.tgz",
"integrity": "sha512-JjBTFTAvuTgANXx82a5vzK9JLSMoV6V3LBVn4Uhdso6t7vXrGx7g1Cd2r6NYSsxrYbQGFCMqBDhFHyK5q2UvcQ=="
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.2.3.tgz",
"integrity": "sha512-slWRdJkbTZ+PjkyJnE30Uid64eHwbwa1Q25INCAYfZlK4o6ylagBy/Le9eWntqJFoFT93ikUKMv47GZ4gTwHkw=="
},
"merge2": {
"version": "1.4.1",
@@ -3018,9 +3018,9 @@
}
},
"regenerator-runtime": {
"version": "0.13.10",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz",
"integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw=="
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"regexpp": {
"version": "3.2.0",

View File

@@ -1,6 +1,6 @@
{
"name": "dicecloud",
"version": "2.0.45",
"version": "2.0.48",
"description": "Unofficial Online Realtime D&D 5e App",
"license": "GPL-3.0",
"repository": {
@@ -20,10 +20,10 @@
"npm": "6.13.x"
},
"dependencies": {
"@babel/runtime": "^7.20.1",
"@babel/runtime": "^7.20.6",
"@chenfengyuan/vue-countdown": "^1.1.5",
"@tozd/vue-observer-utils": "^0.5.0",
"aws-sdk": "^2.1258.0",
"aws-sdk": "^2.1262.0",
"bcrypt": "^5.1.0",
"chroma-js": "^2.4.2",
"css-box-shadow": "^1.0.0-3",
@@ -31,10 +31,10 @@
"ddp-rate-limiter-mixin": "^1.1.10",
"discord.js": "^12.5.3",
"dompurify": "^2.4.1",
"ignore": "^5.2.0",
"ignore": "^5.2.1",
"ignore-styles": "^5.0.1",
"lodash": "^4.17.20",
"marked": "^4.2.2",
"marked": "^4.2.3",
"meteor-node-stubs": "^1.2.5",
"minify-css-string": "^1.0.0",
"moo": "^0.5.2",
@@ -58,8 +58,8 @@
"vuex": "^3.1.3"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
"@vue/compiler-dom": "^3.2.45",
"chai": "^4.3.7",
"eslint": "^7.32.0",