Added actions to tabletop, used character logs instead.
This commit is contained in:
@@ -4,6 +4,8 @@ import LogContentSchema from '/imports/api/creature/log/LogContentSchema.js';
|
||||
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
||||
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
||||
import {assertEditPermission} from '/imports/api/creature/creatures/creaturePermissions.js';
|
||||
import {assertUserInTabletop} from '/imports/api/tabletop/methods/shared/tabletopPermissions.js';
|
||||
|
||||
import {parse, prettifyParseError} from '/imports/parser/parser.js';
|
||||
import resolve, { toString } from '/imports/parser/resolve.js';
|
||||
const PER_CREATURE_LOG_LIMIT = 100;
|
||||
@@ -40,6 +42,12 @@ let CreatureLogSchema = new SimpleSchema({
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
tabletopId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
optional: true,
|
||||
},
|
||||
creatureName: {
|
||||
type: String,
|
||||
optional: true,
|
||||
@@ -105,6 +113,7 @@ const insertCreatureLog = new ValidatedMethod({
|
||||
'settings.discordWebhook': 1,
|
||||
name: 1,
|
||||
avatarPicture: 1,
|
||||
tabletop: 1,
|
||||
}});
|
||||
assertEditPermission(creature, this.userId);
|
||||
// Build the new log
|
||||
@@ -113,6 +122,25 @@ const insertCreatureLog = new ValidatedMethod({
|
||||
},
|
||||
});
|
||||
|
||||
const insertTabletopLog = new ValidatedMethod({
|
||||
name: 'creatureLogs.methods.insertTabletopLog',
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
validate: new SimpleSchema({
|
||||
log: CreatureLogSchema.omit('date'),
|
||||
}).validator(),
|
||||
run({log}){
|
||||
const tabletopId = log.tabletopId;
|
||||
assertUserInTabletop(tabletopId, this.userId);
|
||||
// Build the new log
|
||||
let id = insertCreatureLogWork({log, method: this})
|
||||
return id;
|
||||
},
|
||||
});
|
||||
|
||||
export function insertCreatureLogWork({log, creature, method}){
|
||||
// Build the new log
|
||||
if (typeof log === 'string'){
|
||||
@@ -120,12 +148,19 @@ export function insertCreatureLogWork({log, creature, method}){
|
||||
}
|
||||
if (!log.content?.length) return;
|
||||
log.date = new Date();
|
||||
if (creature) log.tabletopId = creature.tabletop;
|
||||
// Insert it
|
||||
let id = CreatureLogs.insert(log);
|
||||
if (Meteor.isServer){
|
||||
method?.unblock();
|
||||
removeOldLogs(creature._id);
|
||||
logWebhook({log, creature});
|
||||
if (creature){
|
||||
removeOldLogs(creature._id);
|
||||
logWebhook({log, creature});
|
||||
}
|
||||
if (log.tabletopId){
|
||||
// Todo remove old tabletop logs
|
||||
// Log webhook if it's different to creature webhook
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@@ -210,4 +245,4 @@ const logRoll = new ValidatedMethod({
|
||||
});
|
||||
|
||||
export default CreatureLogs;
|
||||
export { CreatureLogSchema, insertCreatureLog, logRoll};
|
||||
export { CreatureLogSchema, insertCreatureLog, logRoll, insertTabletopLog};
|
||||
|
||||
@@ -214,7 +214,7 @@ if (Meteor.isServer && Meteor.settings.useS3) {
|
||||
}
|
||||
} else {
|
||||
if (Meteor.isServer){
|
||||
console.log('No S3 details specified, files will be stored in the local filesystem');
|
||||
// console.log('No S3 details specified, files will be stored in the local filesystem');
|
||||
}
|
||||
createS3FilesCollection = function({
|
||||
collectionName,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Tabletops from '/imports/api/tabletop/Tabletops.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import Messages from '/imports/api/tabletop/Messages.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js';
|
||||
|
||||
Meteor.publish('tabletops', function(){
|
||||
var userId = this.userId;
|
||||
@@ -47,14 +48,17 @@ Meteor.publish('tabletop', function(tabletopId){
|
||||
initiativeRoll: 1,
|
||||
},
|
||||
});
|
||||
let recentMessages = Messages.find({
|
||||
const creatureIds = creatureSummaries.map(c => c._id);
|
||||
let properties = CreatureProperties.find({
|
||||
'ancestors.0.id': {$in: creatureIds},
|
||||
removed: {$ne: true},
|
||||
});
|
||||
const logs = CreatureLogs.find({
|
||||
tabletopId,
|
||||
}, {
|
||||
sort: {
|
||||
timeStamp: -1,
|
||||
},
|
||||
limit: 100,
|
||||
limit: 50,
|
||||
sort: {date: -1},
|
||||
});
|
||||
return [ tabletopCursor, creatureSummaries, recentMessages]
|
||||
return [ tabletopCursor, creatureSummaries, properties, logs]
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if<template>
|
||||
<template>
|
||||
<div class="character-sheet fill-height">
|
||||
<v-fade-transition mode="out-in">
|
||||
<div
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<template lang="html">
|
||||
<div class="mini-character-sheet" />
|
||||
<v-card
|
||||
hover
|
||||
@click="$emit('click')"
|
||||
>
|
||||
Character sheet
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const AddCreaturePropertyDialog = () => import('/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue');
|
||||
const ArchiveDialog = () => import('/imports/ui/creature/archive/ArchiveDialog.vue');
|
||||
const CastSpellWithSlotDialog = () => import('/imports/ui/properties/components/spells/CastSpellWithSlotDialog.vue');
|
||||
const CharacterSheetDialog = () => import('/imports/ui/tabletop/CharacterSheetDialog.vue');
|
||||
const CreatureFormDialog = () => import('/imports/ui/creature/CreatureFormDialog.vue');
|
||||
const CreaturePropertyCreationDialog = () => import('/imports/ui/creature/creatureProperties/CreaturePropertyCreationDialog.vue');
|
||||
const CreaturePropertyDialog = () => import('/imports/ui/creature/creatureProperties/CreaturePropertyDialog.vue');
|
||||
@@ -28,6 +29,7 @@ export default {
|
||||
AddCreaturePropertyDialog,
|
||||
ArchiveDialog,
|
||||
CastSpellWithSlotDialog,
|
||||
CharacterSheetDialog,
|
||||
CreatureFormDialog,
|
||||
CreaturePropertyCreationDialog,
|
||||
CreaturePropertyDialog,
|
||||
|
||||
@@ -1,48 +1,20 @@
|
||||
<template lang="html">
|
||||
<div
|
||||
style="height: 100%; overflow: hidden;"
|
||||
class="character-log layout column justify-end"
|
||||
>
|
||||
<v-slide-y-reverse-transition
|
||||
group
|
||||
hide-on-leave
|
||||
class="card-raised-background flex layout column reverse align-end pa-3"
|
||||
style="overflow: auto;"
|
||||
>
|
||||
<log-entry
|
||||
v-for="log in logs"
|
||||
:key="log._id"
|
||||
:model="log"
|
||||
/>
|
||||
</v-slide-y-reverse-transition>
|
||||
<v-card>
|
||||
<v-text-field
|
||||
v-model="input"
|
||||
class="mx-2 mb-2"
|
||||
persistent-hint
|
||||
style="flex-grow: 0"
|
||||
append-outer-icon="mdi-send"
|
||||
:hint="inputHint"
|
||||
:error-messages="inputError"
|
||||
:disabled="!editPermission"
|
||||
@click:append-outer="submit"
|
||||
@keyup.enter="submit"
|
||||
/>
|
||||
</v-card>
|
||||
</div>
|
||||
<log-component
|
||||
:logs="logs"
|
||||
:edit-permission="editPermission"
|
||||
@submit="submit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import CreatureLogs, { logRoll } from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
|
||||
import { parse, prettifyParseError } from '/imports/parser/parser.js';
|
||||
import resolve, { toString } from '/imports/parser/resolve.js';
|
||||
import LogEntry from '/imports/ui/log/LogEntry.vue';
|
||||
import LogComponent from '/imports/ui/log/LogComponent.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LogEntry,
|
||||
LogComponent,
|
||||
},
|
||||
props: {
|
||||
creatureId: {
|
||||
@@ -50,49 +22,14 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
inputHint: undefined,
|
||||
inputError: undefined,
|
||||
input: undefined,
|
||||
}},
|
||||
watch: {
|
||||
input(value){
|
||||
this.input = value;
|
||||
this.inputHint = this.inputError = undefined;
|
||||
if (!this.input) return;
|
||||
let result;
|
||||
try {
|
||||
result = parse(value);
|
||||
} catch (e){
|
||||
if (e.constructor.name === 'EndOfInputError'){
|
||||
this.inputError = '...';
|
||||
} else {
|
||||
let error = prettifyParseError(e);
|
||||
this.inputError = error;
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let {result: compiled} = resolve('compile', result, this.creature.variables);
|
||||
this.inputHint = toString(compiled);
|
||||
return;
|
||||
} catch (e){
|
||||
console.warn(e);
|
||||
this.inputError = 'Compilation error';
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
if (this.inputError || !this.input) return;
|
||||
submit(input){
|
||||
logRoll.call({
|
||||
roll: this.input,
|
||||
roll: input,
|
||||
creatureId: this.creatureId,
|
||||
}, (error) => {
|
||||
if (error) console.error(error);
|
||||
});
|
||||
this.input = '';
|
||||
},
|
||||
},
|
||||
meteor: {
|
||||
|
||||
98
app/imports/ui/log/LogComponent.vue
Normal file
98
app/imports/ui/log/LogComponent.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<template lang="html">
|
||||
<div
|
||||
style="height: 100%; overflow: hidden;"
|
||||
class="character-log layout column justify-end"
|
||||
>
|
||||
<v-slide-y-reverse-transition
|
||||
group
|
||||
hide-on-leave
|
||||
class="card-raised-background flex layout column reverse align-end pa-3"
|
||||
style="overflow: auto;"
|
||||
>
|
||||
<log-entry
|
||||
v-for="log in logs"
|
||||
:key="log._id"
|
||||
:model="log"
|
||||
:show-name="showName"
|
||||
/>
|
||||
</v-slide-y-reverse-transition>
|
||||
<v-card>
|
||||
<v-text-field
|
||||
v-model="input"
|
||||
class="mx-2 mb-2"
|
||||
persistent-hint
|
||||
style="flex-grow: 0"
|
||||
append-outer-icon="mdi-send"
|
||||
:hint="inputHint"
|
||||
:error-messages="inputError"
|
||||
:disabled="!editPermission"
|
||||
@click:append-outer="submit"
|
||||
@keyup.enter="submit"
|
||||
/>
|
||||
</v-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import LogEntry from '/imports/ui/log/LogEntry.vue';
|
||||
import { parse, prettifyParseError } from '/imports/parser/parser.js';
|
||||
import resolve, { toString } from '/imports/parser/resolve.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LogEntry,
|
||||
},
|
||||
props: {
|
||||
logs: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
editPermission: Boolean,
|
||||
showName: Boolean,
|
||||
},
|
||||
data(){return {
|
||||
inputHint: undefined,
|
||||
inputError: undefined,
|
||||
input: undefined,
|
||||
}},
|
||||
watch: {
|
||||
input(value){
|
||||
this.input = value;
|
||||
this.inputHint = this.inputError = undefined;
|
||||
if (!this.input) return;
|
||||
let result;
|
||||
try {
|
||||
result = parse(value);
|
||||
} catch (e){
|
||||
if (e.constructor.name === 'EndOfInputError'){
|
||||
this.inputError = '...';
|
||||
} else {
|
||||
let error = prettifyParseError(e);
|
||||
this.inputError = error;
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let {result: compiled} = resolve('compile', result, this.creature.variables);
|
||||
this.inputHint = toString(compiled);
|
||||
return;
|
||||
} catch (e){
|
||||
console.warn(e);
|
||||
this.inputError = 'Compilation error';
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
if (this.inputError || !this.input) return;
|
||||
this.$emit('submit', this.input);
|
||||
this.input = '';
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
</style>
|
||||
@@ -2,6 +2,9 @@
|
||||
<v-card
|
||||
class="ma-2 log-entry"
|
||||
>
|
||||
<v-card-title v-if="showName && model.creatureName">
|
||||
{{ model.creatureName }}
|
||||
</v-card-title>
|
||||
<v-card-text
|
||||
v-if="model.text || (model.content && model.content.length)"
|
||||
class="pa-2"
|
||||
@@ -23,6 +26,7 @@ export default {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
showName: Boolean,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
55
app/imports/ui/tabletop/CharacterSheetDialog.vue
Normal file
55
app/imports/ui/tabletop/CharacterSheetDialog.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<dialog-base>
|
||||
<template #replace-toolbar>
|
||||
<v-tabs
|
||||
v-if="creature && creature.settings"
|
||||
v-model="tab"
|
||||
:color="$vuetify.theme.themes.dark.primary"
|
||||
>
|
||||
<v-tab>
|
||||
Stats
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Features
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Inventory
|
||||
</v-tab>
|
||||
<v-tab v-if="!creature.settings.hideSpellsTab">
|
||||
Spells
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Character
|
||||
</v-tab>
|
||||
<v-tab v-if="creature.settings.showTreeTab">
|
||||
Tree
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</template>
|
||||
<character-sheet
|
||||
show-menu-button
|
||||
:creature-id="creatureId"
|
||||
/>
|
||||
</dialog-base>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
|
||||
import CharacterSheet from '/imports/ui/creature/character/CharacterSheet.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DialogBase,
|
||||
CharacterSheet,
|
||||
},
|
||||
props: {
|
||||
creatureId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
tab: 0,
|
||||
}},
|
||||
}
|
||||
</script>
|
||||
@@ -41,12 +41,6 @@ export default {
|
||||
actions(){
|
||||
return getProperties(this.creatureId, 'action');
|
||||
},
|
||||
attacks(){
|
||||
return getProperties(this.creatureId, 'attack');
|
||||
},
|
||||
spells(){
|
||||
return getProperties(this.creatureId, 'spell');
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -7,32 +7,68 @@
|
||||
dense
|
||||
class="initiative-row"
|
||||
style="flex-wrap: nowrap; overflow-x: auto;"
|
||||
@wheel="transformScroll($event)"
|
||||
>
|
||||
<tabletop-creature-card
|
||||
v-for="creature in creatures"
|
||||
:key="creature._id"
|
||||
:model="creature"
|
||||
:active="activeCreature === creature._id"
|
||||
@click="activeCreature = creature._id"
|
||||
/>
|
||||
<v-card
|
||||
class="layout column justify-center align-center"
|
||||
style="height: 150px; min-width: 120px;"
|
||||
data-id="select-creatures"
|
||||
hover
|
||||
@click="addCreature"
|
||||
<div
|
||||
class="layout column ma-1"
|
||||
style="flex-grow: 0;"
|
||||
>
|
||||
<div class="flex layout justify-center align-center">
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
</div>
|
||||
<v-card-title>
|
||||
Add<br>creature
|
||||
</v-card-title>
|
||||
</v-card>
|
||||
<v-btn
|
||||
data-id="select-creatures"
|
||||
class="mb-2"
|
||||
@click="addCreature"
|
||||
>
|
||||
<v-icon left>
|
||||
mdi-plus
|
||||
</v-icon>
|
||||
Add Character
|
||||
</v-btn>
|
||||
<v-btn disabled>
|
||||
<v-icon left>
|
||||
mdi-plus
|
||||
</v-icon>
|
||||
Add Creature
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-row>
|
||||
<tabletop-map class="play-area" />
|
||||
<section class="action-row">
|
||||
<mini-character-sheet />
|
||||
<tabletop-action-cards />
|
||||
</section>
|
||||
<v-row>
|
||||
<tabletop-map class="play-area" />
|
||||
</v-row>
|
||||
<v-footer
|
||||
app
|
||||
inset
|
||||
class="pa-0"
|
||||
style="background: none; box-shadow: none;"
|
||||
>
|
||||
<v-container fluid>
|
||||
<v-row
|
||||
dense
|
||||
class="action-row"
|
||||
style="flex-wrap: nowrap; overflow-x: auto;"
|
||||
@wheel="transformScroll($event)"
|
||||
>
|
||||
<mini-character-sheet
|
||||
v-if="activeCreature"
|
||||
data-id="mini-character-sheet"
|
||||
@click="openCharacterSheetDialog"
|
||||
/>
|
||||
<action-card
|
||||
v-for="action in actions"
|
||||
:key="action._id"
|
||||
:model="action"
|
||||
:data-id="action._id"
|
||||
@click="clickProperty({_id: action._id})"
|
||||
/>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-footer>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
@@ -41,15 +77,29 @@ import addCreaturesToTabletop from '/imports/api/tabletop/methods/addCreaturesTo
|
||||
import TabletopCreatureCard from '/imports/ui/tabletop/TabletopCreatureCard.vue';
|
||||
import TabletopMap from '/imports/ui/tabletop/TabletopMap.vue';
|
||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||
import TabletopActionCards from '/imports/ui/tabletop/TabletopActionCards.vue';
|
||||
import MiniCharacterSheet from '/imports/ui/creature/character/MiniCharacterSheet.vue';
|
||||
import snackbar from '/imports/ui/components/snackbars/SnackbarQueue.js';
|
||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||
import ActionCard from '/imports/ui/properties/components/actions/ActionCard.vue';
|
||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
|
||||
|
||||
function getProperties(ancestorId, type){
|
||||
if (!ancestorId) return [];
|
||||
return CreatureProperties.find({
|
||||
'ancestors.id': ancestorId,
|
||||
type,
|
||||
removed: {$ne: true},
|
||||
inactive: {$ne: true},
|
||||
}, {
|
||||
sort: {order: 1}
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TabletopCreatureCard,
|
||||
TabletopMap,
|
||||
TabletopActionCards,
|
||||
ActionCard,
|
||||
MiniCharacterSheet,
|
||||
},
|
||||
props: {
|
||||
@@ -58,6 +108,10 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
reactiveProvide: {
|
||||
name: 'context',
|
||||
include: ['editPermission'],
|
||||
},
|
||||
data(){ return {
|
||||
activeCreature: undefined,
|
||||
}},
|
||||
@@ -70,6 +124,20 @@ export default {
|
||||
creatures(){
|
||||
return Creatures.find({tabletop: this.model._id});
|
||||
},
|
||||
actions(){
|
||||
return getProperties(this.activeCreature, 'action').map(a => {
|
||||
delete a.summary;
|
||||
return a;
|
||||
});
|
||||
},
|
||||
editPermission(){
|
||||
try {
|
||||
assertEditPermission(this.activeCreature, Meteor.userId());
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addCreature(){
|
||||
@@ -89,6 +157,29 @@ export default {
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
openCharacterSheetDialog(){
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'character-sheet-dialog',
|
||||
elementId: 'mini-character-sheet',
|
||||
data: {
|
||||
creatureId: this.activeCreature,
|
||||
},
|
||||
});
|
||||
},
|
||||
clickProperty({_id}){
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'creature-property-dialog',
|
||||
elementId: `${_id}`,
|
||||
data: {_id},
|
||||
});
|
||||
},
|
||||
transformScroll(event) {
|
||||
if (!event.deltaY) {
|
||||
return;
|
||||
}
|
||||
event.currentTarget.scrollLeft += event.deltaY + event.deltaX;
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,8 +188,17 @@ export default {
|
||||
<style lang="css" scoped>
|
||||
.initiative-row > .v-card {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
height: 162px;
|
||||
width: 100px;
|
||||
margin: 4px;
|
||||
}
|
||||
.action-row > .v-card {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
max-height: 320px;
|
||||
width: 200px;
|
||||
margin: 4px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<template lang="html">
|
||||
<v-card
|
||||
style="height: 150px; min-width: 120px;"
|
||||
:color="active ? 'primary' : ''"
|
||||
hover
|
||||
@mouseover="hover = true"
|
||||
@mouseleave="hover = false"
|
||||
@click="$emit('click')"
|
||||
>
|
||||
<v-img
|
||||
:src="model.picture"
|
||||
@@ -12,17 +17,26 @@
|
||||
>
|
||||
{{ model.name }}
|
||||
</div>
|
||||
<card-highlight :active="hover" />
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import CardHighlight from '/imports/ui/components/CardHighlight.vue';
|
||||
export default {
|
||||
components: {
|
||||
CardHighlight,
|
||||
},
|
||||
props: {
|
||||
model: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
active: Boolean,
|
||||
},
|
||||
data(){return {
|
||||
hover: false,
|
||||
}},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,51 +1,50 @@
|
||||
<template lang="html">
|
||||
<div class="tabletop-log">
|
||||
<div class="messages layout column justify-end align-end">
|
||||
<div
|
||||
v-for="message in messages"
|
||||
:key="message._id"
|
||||
class="message"
|
||||
>
|
||||
{{ message.content }}
|
||||
</div>
|
||||
</div>
|
||||
<v-textarea
|
||||
v-model="messageContent"
|
||||
@keyup.enter.prevent="sendMessage"
|
||||
/>
|
||||
</div>
|
||||
<log-component
|
||||
:logs="logs"
|
||||
:edit-permission="context.editPermission"
|
||||
show-name
|
||||
@submit="submit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import Messages, { sendMessage } from '/imports/api/tabletop/Messages.js';
|
||||
import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import insertTabletopLog from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import LogComponent from '/imports/ui/log/LogComponent.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LogComponent,
|
||||
},
|
||||
inject: {
|
||||
context: {
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
props: {
|
||||
tabletopId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data(){ return {
|
||||
messageContent: '',
|
||||
}},
|
||||
meteor: {
|
||||
messages() {
|
||||
return Messages.find({
|
||||
logs() {
|
||||
return CreatureLogs.find({
|
||||
tabletopId: this.tabletopId,
|
||||
}, {
|
||||
sort: {
|
||||
timeStamp: 1,
|
||||
},
|
||||
sort: {date: -1},
|
||||
limit: 50
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
sendMessage(){
|
||||
sendMessage.call({
|
||||
content: this.messageContent,
|
||||
submit(){
|
||||
insertTabletopLog.call({
|
||||
content: this.logContent,
|
||||
tabletopId: this.tabletopId,
|
||||
}, (error) => {
|
||||
if (error) console.error(error);
|
||||
});
|
||||
this.messageContent = '';
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user