Merge branch 'develop' into version-2-tabletop
This commit is contained in:
@@ -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({
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -195,7 +195,7 @@ export default {
|
||||
} else {
|
||||
this.$store.commit(
|
||||
'setTabForCharacterSheet',
|
||||
{id: creatureId, tab: 5}
|
||||
{id: creatureId, tab: 'build'}
|
||||
);
|
||||
this.$emit('pop', creatureId);
|
||||
defer(() => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</v-toolbar-title>
|
||||
<div>
|
||||
<p v-if="name">
|
||||
Type "{{ name }}" to permanenetly delete the character
|
||||
Type "{{ name }}" to permanently delete the character
|
||||
</p>
|
||||
<v-text-field
|
||||
v-if="name"
|
||||
|
||||
@@ -46,9 +46,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>
|
||||
@@ -58,6 +55,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>
|
||||
|
||||
@@ -39,27 +39,45 @@
|
||||
<v-icon>mdi-dots-vertical</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list v-if="editPermission">
|
||||
<v-list-item @click="deleteCharacter">
|
||||
<v-list>
|
||||
<v-list-item :to="printUrl">
|
||||
<v-list-item-title>
|
||||
<v-icon>mdi-delete</v-icon> Delete
|
||||
<v-icon left>
|
||||
mdi-printer
|
||||
</v-icon> Print
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="showCharacterForm">
|
||||
<template v-if="editPermission">
|
||||
<v-list-item @click="deleteCharacter">
|
||||
<v-list-item-title>
|
||||
<v-icon left>
|
||||
mdi-delete
|
||||
</v-icon> Delete
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="showCharacterForm">
|
||||
<v-list-item-title>
|
||||
<v-icon left>
|
||||
mdi-pencil
|
||||
</v-icon> Edit details
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="showShareDialog">
|
||||
<v-list-item-title>
|
||||
<v-icon left>
|
||||
mdi-share-variant
|
||||
</v-icon> Sharing
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-list-item
|
||||
v-else
|
||||
@click="unshareWithMe"
|
||||
>
|
||||
<v-list-item-title>
|
||||
<v-icon>mdi-pencil</v-icon> Edit details
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="showShareDialog">
|
||||
<v-list-item-title>
|
||||
<v-icon>mdi-share-variant</v-icon> Sharing
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<v-list v-else>
|
||||
<v-list-item @click="unshareWithMe">
|
||||
<v-list-item-title>
|
||||
<v-icon>mdi-delete</v-icon> Unshare with me
|
||||
<v-icon left>
|
||||
mdi-delete
|
||||
</v-icon> Unshare with me
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
@@ -101,9 +119,6 @@
|
||||
<v-tab>
|
||||
Stats
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Features
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Actions
|
||||
</v-tab>
|
||||
@@ -113,6 +128,9 @@
|
||||
<v-tab>
|
||||
Inventory
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Features
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Journal
|
||||
</v-tab>
|
||||
@@ -144,6 +162,7 @@ import isDarkColor from '/imports/client/ui/utility/isDarkColor.js';
|
||||
import CharacterSheetFab from '/imports/client/ui/creature/character/CharacterSheetFab.vue';
|
||||
import getThemeColor from '/imports/client/ui/utility/getThemeColor.js';
|
||||
import SharedIcon from '/imports/client/ui/components/SharedIcon.vue';
|
||||
import getCreatureUrlName from '/imports/api/creature/creatures/getCreatureUrlName.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -167,6 +186,9 @@ export default {
|
||||
isDark() {
|
||||
return isDarkColor(this.toolbarColor);
|
||||
},
|
||||
printUrl() {
|
||||
return `/print-character/${this.creature._id}/${getCreatureUrlName(this.creature)}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
@remove="softRemove"
|
||||
/>
|
||||
<div
|
||||
v-if="!creature.settings.hideRestButtons || (properties.action.event && properties.action.event.length)"
|
||||
v-if="!creature.settings.hideRestButtons || (properties.action && properties.action.event && properties.action.event.length)"
|
||||
class="character-buttons"
|
||||
>
|
||||
<v-card>
|
||||
@@ -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 => {
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
light
|
||||
>
|
||||
<div class="page pa-3">
|
||||
<div class="px-3 d-flex align-center">
|
||||
<div class="title-block px-3 d-flex align-center">
|
||||
<div class="logo-background" />
|
||||
<div class="creature-name mr-3">
|
||||
{{ creature.name }}
|
||||
@@ -42,7 +42,7 @@
|
||||
{{ creature.alignment }} {{ background }}
|
||||
</div>
|
||||
<dir v-if="race || creature.gender">
|
||||
{{ race }} {{ creature.gender }}
|
||||
{{ creature.gender }} {{ race }}
|
||||
</dir>
|
||||
<div v-if="level && classes && classes.length === 1">
|
||||
Level {{ level }} {{ classes[0].name }}
|
||||
@@ -236,9 +236,33 @@ export default {
|
||||
color: black;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.character-sheet-printed * {
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
cursor: unset !important;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.character-sheet-printed .column-layout, .character-sheet-printed .column-layout.wide-columns {
|
||||
position:relative;
|
||||
width: 100%;
|
||||
widows: 0;
|
||||
orphans: 0;
|
||||
-webkit-column-fill: balance-all;
|
||||
column-fill: balance-all;
|
||||
}
|
||||
|
||||
.character-sheet-printed .column-layout>div {
|
||||
position:relative;
|
||||
}
|
||||
.character-sheet-printed .column-layout > div > * {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.character-sheet-printed .inactive {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
@@ -253,8 +277,6 @@ export default {
|
||||
background-image: url(/crown-dice-logo-cropped-transparent.png);
|
||||
background-size: contain;
|
||||
background-position: 0 center;
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
|
||||
.character-sheet-printed .v-divider {
|
||||
@@ -265,39 +287,26 @@ export default {
|
||||
.character-sheet-printed .double-border {
|
||||
position: relative;
|
||||
padding: 11px 10px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.character-sheet-printed .double-border::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border-image-source: url(/images/print/doubleLineImageBorder.png);
|
||||
border-image-slice: 110 126 fill;
|
||||
border-image-width: 16px;
|
||||
border-image-repeat: stretch;
|
||||
box-sizing: content-box;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.character-sheet-printed .octagon-border {
|
||||
position: relative;
|
||||
padding: 4px 20px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
.character-sheet-printed .octagon-border::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border-image: url(/images/print/octagonBorder.png) 124 118 fill;
|
||||
border-image-width: 22px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.character-sheet-printed .span-all {
|
||||
page-break-after: avoid;
|
||||
break-after: avoid;
|
||||
}
|
||||
.span-all + div {
|
||||
page-break-before: avoid;
|
||||
break-before: avoid;
|
||||
}
|
||||
|
||||
.character-sheet-printed .stats .label {
|
||||
@@ -326,10 +335,32 @@ export default {
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
header {
|
||||
display: none !important;
|
||||
@page {
|
||||
size: auto;
|
||||
margin: 8mm 8mm 8mm 8mm;
|
||||
}
|
||||
nav {
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
.character-sheet-printed .page {
|
||||
width: 100%;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.character-sheet-printed .column-layout {
|
||||
padding: 4px 0 !important;
|
||||
}
|
||||
.character-sheet-printed .title-block {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 4px !important;
|
||||
}
|
||||
.v-main, .v-application, .v-application--wrap, .character-sheet-printed {
|
||||
display: block !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
html {
|
||||
background-color: white !important;
|
||||
}
|
||||
header, nav, .v-snack, .dialog-stack {
|
||||
display: none !important;
|
||||
}
|
||||
.v-main {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<v-app-bar
|
||||
app
|
||||
class="character-sheet-printed-toolbar"
|
||||
:color="toolbarColor"
|
||||
:dark="isDark"
|
||||
:light="!isDark"
|
||||
clipped-right
|
||||
:extended="$vuetify.breakpoint.smAndUp"
|
||||
:tabs="$vuetify.breakpoint.smAndUp"
|
||||
dense
|
||||
>
|
||||
<v-app-bar-nav-icon @click="toggleDrawer" />
|
||||
<v-btn
|
||||
icon
|
||||
:to="characterUrl"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<v-toolbar-title>
|
||||
<v-fade-transition mode="out-in">
|
||||
<div :key="$store.state.pageTitle">
|
||||
{{ $store.state.pageTitle }}
|
||||
</div>
|
||||
</v-fade-transition>
|
||||
</v-toolbar-title>
|
||||
<v-spacer />
|
||||
<div
|
||||
slot="extension"
|
||||
style="width: 100%"
|
||||
>
|
||||
<v-btn
|
||||
class="print-fab"
|
||||
color="accent"
|
||||
elevation="4"
|
||||
fab
|
||||
@click="print"
|
||||
>
|
||||
<v-icon>mdi-printer</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-app-bar>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import { mapMutations } from 'vuex';
|
||||
import isDarkColor from '/imports/client/ui/utility/isDarkColor.js';
|
||||
import getThemeColor from '/imports/client/ui/utility/getThemeColor.js';
|
||||
import getCreatureUrlName from '/imports/api/creature/creatures/getCreatureUrlName.js';
|
||||
|
||||
export default {
|
||||
inject: {
|
||||
context: { default: {} }
|
||||
},
|
||||
computed: {
|
||||
creatureId() {
|
||||
return this.$route.params.id;
|
||||
},
|
||||
toolbarColor() {
|
||||
if (this.creature && this.creature.color) {
|
||||
return this.creature.color;
|
||||
} else {
|
||||
return getThemeColor('secondary');
|
||||
}
|
||||
},
|
||||
isDark() {
|
||||
return isDarkColor(this.toolbarColor);
|
||||
},
|
||||
characterUrl() {
|
||||
if (!this.creature) return;
|
||||
return `/character/${this.creature._id}/${getCreatureUrlName(this.creature)}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
'toggleDrawer',
|
||||
]),
|
||||
print() {
|
||||
print();
|
||||
},
|
||||
},
|
||||
meteor: {
|
||||
creature() {
|
||||
return Creatures.findOne(this.creatureId);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.print-fab {
|
||||
position: absolute;
|
||||
bottom: -24px;
|
||||
right: 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,6 @@
|
||||
<template lang="html">
|
||||
<div
|
||||
class="inventory"
|
||||
style="page-break-before: always;"
|
||||
>
|
||||
<column-layout wide-columns>
|
||||
<div class="span-all">
|
||||
@@ -62,7 +61,7 @@
|
||||
>
|
||||
<div
|
||||
:key="container._id"
|
||||
class="span-all container-header"
|
||||
class="span-all"
|
||||
>
|
||||
<printed-container
|
||||
class="octagon-border"
|
||||
@@ -232,22 +231,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.octagon-border {
|
||||
position: relative;
|
||||
padding: 4px 20px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
.octagon-border::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border-image: url(/images/print/octagonBorder.png) 124 118 fill;
|
||||
border-image-width: 22px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14pt;
|
||||
@@ -262,9 +245,4 @@ export default {
|
||||
.inventory-stat > .v-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.container-header {
|
||||
page-break-after: avoid;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template lang="html">
|
||||
<div
|
||||
class="spells"
|
||||
style="page-break-before: always;"
|
||||
>
|
||||
<column-layout wide-columns>
|
||||
<div class="span-all">
|
||||
|
||||
@@ -2,97 +2,104 @@
|
||||
<div class="stats">
|
||||
<column-layout>
|
||||
<div
|
||||
v-if="abilities.length"
|
||||
class="ability-scores"
|
||||
v-for="ability in abilities"
|
||||
:key="ability._id"
|
||||
>
|
||||
<div class="layout flex column">
|
||||
<div
|
||||
v-for="ability in abilities"
|
||||
:key="ability._id"
|
||||
class="ability"
|
||||
>
|
||||
<div class="score">
|
||||
<div class="double-border top big-number">
|
||||
<template v-if="creature.settings.swapScoresAndMods">
|
||||
{{ ability.total }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ numberToSignedString(ability.modifier) }}
|
||||
</template>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<template v-if="creature.settings.swapScoresAndMods">
|
||||
{{ numberToSignedString(ability.modifier) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ ability.total }}
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
class="ability"
|
||||
>
|
||||
<div class="score">
|
||||
<div class="double-border top big-number">
|
||||
<template v-if="creature.settings.swapScoresAndMods">
|
||||
{{ ability.total }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ numberToSignedString(ability.modifier) }}
|
||||
</template>
|
||||
</div>
|
||||
<div class="double-border name label">
|
||||
{{ ability.name }}
|
||||
<div class="bottom">
|
||||
<template v-if="creature.settings.swapScoresAndMods">
|
||||
{{ numberToSignedString(ability.modifier) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ ability.total }}
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="double-border name label">
|
||||
{{ ability.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="toggle in toggles"
|
||||
:key="toggle._id"
|
||||
class="number-label"
|
||||
>
|
||||
<div class="box double-border" />
|
||||
<div class="label double-border">
|
||||
{{ toggle.name }}
|
||||
<div
|
||||
class="number-label"
|
||||
>
|
||||
<div class="box double-border" />
|
||||
<div class="label double-border">
|
||||
{{ toggle.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="stat in stats"
|
||||
:key="stat._id"
|
||||
class="number-label"
|
||||
:class="stat.variableName == 'armor' && 'shield-number-label'"
|
||||
>
|
||||
<div
|
||||
:class="stat.variableName == 'armor' ? 'shield-border' : 'octagon-border'"
|
||||
class="number big-number"
|
||||
class="number-label"
|
||||
:class="stat.variableName == 'armor' && 'shield-number-label'"
|
||||
>
|
||||
{{ stat.value }}
|
||||
</div>
|
||||
<div class="label double-border">
|
||||
{{ stat.name }}
|
||||
<div
|
||||
:class="stat.variableName == 'armor' ? 'shield-border' : 'octagon-border'"
|
||||
class="number big-number"
|
||||
>
|
||||
{{ stat.value }}
|
||||
</div>
|
||||
<div class="label double-border">
|
||||
{{ stat.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="modifier in modifiers"
|
||||
:key="modifier._id"
|
||||
class="number-label"
|
||||
>
|
||||
<div class="number octagon-border big-number">
|
||||
{{ numberToSignedString(modifier.value) }}
|
||||
</div>
|
||||
<div class="label double-border">
|
||||
{{ modifier.name }}
|
||||
<div
|
||||
class="number-label"
|
||||
>
|
||||
<div class="number octagon-border big-number">
|
||||
{{ numberToSignedString(modifier.value) }}
|
||||
</div>
|
||||
<div class="label double-border">
|
||||
{{ modifier.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="check in checks"
|
||||
:key="check._id"
|
||||
class="number-label"
|
||||
>
|
||||
<div class="number octagon-border big-number">
|
||||
{{ numberToSignedString(check.value) }}
|
||||
</div>
|
||||
<div class="label double-border">
|
||||
{{ check.name }}
|
||||
<div
|
||||
class="number-label"
|
||||
>
|
||||
<div class="number octagon-border big-number">
|
||||
{{ numberToSignedString(check.value) }}
|
||||
</div>
|
||||
<div class="label double-border">
|
||||
{{ check.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="healthBar in healthBars"
|
||||
:key="healthBar._id"
|
||||
class="m-2"
|
||||
>
|
||||
<div class="double-border">
|
||||
<div class="label">
|
||||
@@ -115,7 +122,6 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="hitDice.length"
|
||||
class="hit-dice m-2"
|
||||
>
|
||||
<div class="double-border">
|
||||
<div>
|
||||
@@ -528,21 +534,10 @@ export default {
|
||||
position: relative;
|
||||
aspect-ratio: 0.87;
|
||||
padding: 12px;
|
||||
}
|
||||
.shield-border::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: url(/images/print/shieldBorder.png);
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
z-index: -1;
|
||||
}
|
||||
.shield-number-label {
|
||||
align-items: center !important;
|
||||
@@ -571,23 +566,13 @@ export default {
|
||||
font-size: 10pt;
|
||||
position: relative;
|
||||
padding: 0 16px;
|
||||
z-index: 2;
|
||||
}
|
||||
.ability .bottom::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: solid white;
|
||||
border-image-source: url(/images/print/upwardPointingBorder.png);
|
||||
border-image-slice: 0 85 fill;
|
||||
border-image-width: 0 16px;
|
||||
border-image-outset: 0px 0px;
|
||||
border-image-repeat: stretch;
|
||||
box-sizing: content-box;
|
||||
z-index: -1;
|
||||
z-index: 2;
|
||||
}
|
||||
.ability .name {
|
||||
margin-top: 10px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="inventory-container">
|
||||
<div class="d-flex justify-center">
|
||||
<property-icon
|
||||
class="ml-2"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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: {},
|
||||
|
||||
@@ -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;"
|
||||
>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user