Character sheet toolbars now match the color of the character
This commit is contained in:
@@ -143,7 +143,15 @@ const updateCreature = new ValidatedMethod({
|
||||
validate({_id, path}){
|
||||
if (!_id) return false;
|
||||
// Allowed fields
|
||||
let allowedFields = ['name', 'alignment', 'gender', 'picture', 'avatarPicture', 'settings'];
|
||||
let allowedFields = [
|
||||
'name',
|
||||
'alignment',
|
||||
'gender',
|
||||
'picture',
|
||||
'avatarPicture',
|
||||
'color',
|
||||
'settings',
|
||||
];
|
||||
if (!allowedFields.includes(path[0])){
|
||||
throw new Meteor.Error('Creatures.methods.update.denied',
|
||||
'This field can\'t be updated using this method');
|
||||
@@ -152,9 +160,15 @@ const updateCreature = new ValidatedMethod({
|
||||
run({_id, path, value}) {
|
||||
let creature = Creatures.findOne(_id);
|
||||
assertEditPermission(creature, this.userId);
|
||||
Creatures.update(_id, {
|
||||
$set: {[path.join('.')]: value},
|
||||
});
|
||||
if (value === undefined || value === null){
|
||||
Creatures.update(_id, {
|
||||
$unset: {[path.join('.')]: 1},
|
||||
});
|
||||
} else {
|
||||
Creatures.update(_id, {
|
||||
$set: {[path.join('.')]: value},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
<template lang="html">
|
||||
<dialog-base>
|
||||
<v-toolbar-title slot="toolbar">
|
||||
Creature Form Dialog
|
||||
</v-toolbar-title>
|
||||
<dialog-base :color="model.color">
|
||||
<template slot="toolbar">
|
||||
<v-toolbar-title>
|
||||
Creature Form Dialog
|
||||
</v-toolbar-title>
|
||||
<v-spacer />
|
||||
<color-picker
|
||||
:value="model.color"
|
||||
@input="value => change({path: ['color'], value})"
|
||||
/>
|
||||
</template>
|
||||
<div>
|
||||
<creature-form
|
||||
:model="model"
|
||||
@@ -27,11 +34,13 @@ import {updateCreature} from '/imports/api/creature/Creatures.js';
|
||||
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
|
||||
import CreatureForm from '/imports/ui/creature/CreatureForm.vue'
|
||||
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
|
||||
import ColorPicker from '/imports/ui/components/ColorPicker.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DialogBase,
|
||||
CreatureForm,
|
||||
ColorPicker,
|
||||
},
|
||||
props: {
|
||||
_id: String,
|
||||
@@ -52,8 +61,16 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
change({path, value, ack}){
|
||||
updateCreature.call({_id: this._id, path, value}, (error, result) =>{
|
||||
ack && ack(error && error.reason || error);
|
||||
updateCreature.call({_id: this._id, path, value}, (error) =>{
|
||||
if (error){
|
||||
if(ack){
|
||||
ack(error && error.reason || error)
|
||||
} else {
|
||||
console.error(error)
|
||||
}
|
||||
} else if (ack) {
|
||||
ack();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
235
app/imports/ui/creature/character/CharacterSheetToolbar.vue
Normal file
235
app/imports/ui/creature/character/CharacterSheetToolbar.vue
Normal file
@@ -0,0 +1,235 @@
|
||||
<template lang="html">
|
||||
<v-toolbar
|
||||
app
|
||||
class="character-sheet-toolbar"
|
||||
:color="creature && creature.color || 'secondary'"
|
||||
dark
|
||||
tabs
|
||||
dense
|
||||
>
|
||||
<v-toolbar-side-icon @click="toggleDrawer" />
|
||||
<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 />
|
||||
<v-fade-transition
|
||||
mode="out-in"
|
||||
>
|
||||
<div :key="$route.meta.title">
|
||||
<v-toolbar-items v-if="creature">
|
||||
<v-btn
|
||||
v-if="editPermission"
|
||||
flat
|
||||
icon
|
||||
@click="recompute(creature._id)"
|
||||
>
|
||||
<v-icon>refresh</v-icon>
|
||||
</v-btn>
|
||||
<v-menu
|
||||
bottom
|
||||
left
|
||||
transition="slide-y-transition"
|
||||
data-id="creature-menu"
|
||||
>
|
||||
<template #activator="{ on }">
|
||||
<v-btn
|
||||
icon
|
||||
v-on="on"
|
||||
>
|
||||
<v-icon>more_vert</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list v-if="editPermission">
|
||||
<v-list-tile @click="deleteCharacter">
|
||||
<v-list-tile-title>
|
||||
<v-icon>delete</v-icon> Delete
|
||||
</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
<v-list-tile @click="showCharacterForm">
|
||||
<v-list-tile-title>
|
||||
<v-icon>create</v-icon> Edit details
|
||||
</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
<v-list-tile @click="showShareDialog">
|
||||
<v-list-tile-title>
|
||||
<v-icon>share</v-icon> Sharing
|
||||
</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
<v-list v-else>
|
||||
<v-list-tile @click="unshareWithMe">
|
||||
<v-list-tile-title>
|
||||
<v-icon>delete</v-icon> Unshare with me
|
||||
</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-toolbar-items>
|
||||
</div>
|
||||
</v-fade-transition>
|
||||
<v-fade-transition
|
||||
slot="extension"
|
||||
mode="out-in"
|
||||
>
|
||||
<div
|
||||
:key="$route.meta.title"
|
||||
style="width: 100%"
|
||||
>
|
||||
<v-tabs
|
||||
v-if="creature"
|
||||
slot="extension"
|
||||
:value="value"
|
||||
centered
|
||||
grow
|
||||
max="100px"
|
||||
@change="e => $emit('input', e)"
|
||||
>
|
||||
<v-tab>
|
||||
Stats
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Features
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Inventory
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Spells
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Persona
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
Tree
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</div>
|
||||
</v-fade-transition>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Creatures from '/imports/api/creature/Creatures.js';
|
||||
import removeCreature from '/imports/api/creature/removeCreature.js';
|
||||
import { mapMutations } from 'vuex';
|
||||
import { theme } from '/imports/ui/theme.js';
|
||||
import { recomputeCreature } from '/imports/api/creature/computation/recomputeCreature.js';
|
||||
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
|
||||
import { updateUserSharePermissions } from '/imports/api/sharing/sharing.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
theme,
|
||||
}},
|
||||
computed: {
|
||||
creatureId(){
|
||||
return this.$route.params.id;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
'toggleDrawer',
|
||||
]),
|
||||
recompute(charId){
|
||||
recomputeCreature.call({charId});
|
||||
},
|
||||
showCharacterForm(){
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'creature-form-dialog',
|
||||
elementId: 'creature-menu',
|
||||
data: {
|
||||
_id: this.creatureId,
|
||||
},
|
||||
});
|
||||
},
|
||||
showShareDialog(){
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'share-dialog',
|
||||
elementId: 'creature-menu',
|
||||
data: {
|
||||
docRef: {
|
||||
id: this.creatureId,
|
||||
collection: 'creatures',
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
deleteCharacter(){
|
||||
let that = this;
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'delete-confirmation-dialog',
|
||||
elementId: 'creature-menu',
|
||||
data: {
|
||||
name: this.creature.name,
|
||||
typeName: 'Character'
|
||||
},
|
||||
callback(confirmation){
|
||||
if(!confirmation) return;
|
||||
removeCreature.call({charId: that.creatureId}, (error) => {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
} else {
|
||||
that.$router.push('/characterList');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
unshareWithMe(){
|
||||
updateUserSharePermissions.call({
|
||||
docRef: {
|
||||
collection: 'creatures',
|
||||
id: this.creatureId,
|
||||
},
|
||||
userId: Meteor.userId(),
|
||||
role: 'none',
|
||||
}, (error) => {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
} else {
|
||||
this.$router.push('/characterList');
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
meteor: {
|
||||
$subscribe: {
|
||||
'singleCharacter'(){
|
||||
return [this.creatureId];
|
||||
},
|
||||
},
|
||||
creature(){
|
||||
return Creatures.findOne(this.creatureId);
|
||||
},
|
||||
editPermission(){
|
||||
try {
|
||||
assertEditPermission(this.creature, Meteor.userId());
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css">
|
||||
.character-sheet-toolbar .v-tabs__container--grow .v-tabs__div {
|
||||
max-width: 120px !important;
|
||||
}
|
||||
.character-sheet-toolbar .v-tabs__bar {
|
||||
background: none !important;
|
||||
}
|
||||
</style>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="inventory">
|
||||
<column-layout>
|
||||
<div>
|
||||
<toolbar-card color="">
|
||||
<toolbar-card :color="$vuetify.theme.secondary">
|
||||
<v-spacer slot="toolbar" />
|
||||
<v-switch
|
||||
v-if="context.editPermission !== false"
|
||||
|
||||
@@ -4,14 +4,17 @@
|
||||
:light="!darkMode"
|
||||
>
|
||||
<v-navigation-drawer
|
||||
v-if="$route.path !== '/countdown'"
|
||||
v-model="drawer"
|
||||
app
|
||||
>
|
||||
<Sidebar />
|
||||
</v-navigation-drawer>
|
||||
<router-view
|
||||
v-model="tabs"
|
||||
name="toolbar"
|
||||
/>
|
||||
<v-toolbar
|
||||
v-if="$route.path !== '/countdown'"
|
||||
v-if="!$route.matched[0].components.toolbar"
|
||||
app
|
||||
color="secondary"
|
||||
dark
|
||||
@@ -116,6 +119,9 @@
|
||||
'toggleDrawer',
|
||||
]),
|
||||
},
|
||||
mounted(){
|
||||
console.log(this.$route);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="sidebar">
|
||||
<v-alert
|
||||
v-if="$route.path !== '/countdown'"
|
||||
icon="priority_high"
|
||||
type="error"
|
||||
dismissible
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { RouterFactory, nativeScrollBehavior } from 'meteor/akryum:vue-router2';
|
||||
import LAUNCH_DATE from '/imports/constants/LAUNCH_DATE.js';
|
||||
import { acceptInviteToken } from '/imports/api/users/Invites.js';
|
||||
|
||||
// Components
|
||||
@@ -10,8 +9,7 @@ import Library from '/imports/ui/pages/Library.vue';
|
||||
import SingleLibraryPage from '/imports/ui/pages/SingleLibraryPage.vue'
|
||||
import SingleLibraryToolbarItems from '/imports/ui/library/SingleLibraryToolbarItems.vue'
|
||||
import CharacterSheetPage from '/imports/ui/pages/CharacterSheetPage.vue';
|
||||
import CharacterSheetToolbarItems from '/imports/ui/creature/character/CharacterSheetToolbarItems.vue';
|
||||
import CharacterSheetToolbarExtension from '/imports/ui/creature/character/CharacterSheetToolbarExtension.vue';
|
||||
import CharacterSheetToolbar from '/imports/ui/creature/character/CharacterSheetToolbar.vue';
|
||||
import SignIn from '/imports/ui/pages/SignIn.vue' ;
|
||||
import Register from '/imports/ui/pages/Register.vue';
|
||||
import IconAdmin from '/imports/ui/icons/IconAdmin.vue';
|
||||
@@ -22,7 +20,6 @@ import InviteSuccess from '/imports/ui/pages/InviteSuccess.vue' ;
|
||||
import InviteError from '/imports/ui/pages/InviteError.vue' ;
|
||||
import NotImplemented from '/imports/ui/pages/NotImplemented.vue';
|
||||
import PatreonLevelTooLow from '/imports/ui/pages/PatreonLevelTooLow.vue';
|
||||
import LaunchCountdown from '/imports/ui/pages/LaunchCountdown.vue';
|
||||
|
||||
let userSubscription = Meteor.subscribe('user');
|
||||
|
||||
@@ -91,17 +88,7 @@ function claimInvite(to, from, next){
|
||||
}
|
||||
|
||||
RouterFactory.configure(factory => {
|
||||
factory.addRoutes([
|
||||
{
|
||||
path: '/countdown',
|
||||
name: 'Countdown',
|
||||
components: {
|
||||
default: LaunchCountdown,
|
||||
},
|
||||
meta: {
|
||||
title: 'Countdown to Launch',
|
||||
},
|
||||
},{
|
||||
factory.addRoutes([{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
components: {
|
||||
@@ -142,8 +129,7 @@ RouterFactory.configure(factory => {
|
||||
path: '/character/:id/:urlName',
|
||||
components: {
|
||||
default: CharacterSheetPage,
|
||||
toolbarExtension: CharacterSheetToolbarExtension,
|
||||
toolbarItems: CharacterSheetToolbarItems,
|
||||
toolbar: CharacterSheetToolbar,
|
||||
},
|
||||
meta: {
|
||||
title: 'Character Sheet',
|
||||
@@ -152,8 +138,7 @@ RouterFactory.configure(factory => {
|
||||
path: '/character/:id',
|
||||
components: {
|
||||
default: CharacterSheetPage,
|
||||
toolbarExtension: CharacterSheetToolbarExtension,
|
||||
toolbarItems: CharacterSheetToolbarItems,
|
||||
toolbar: CharacterSheetToolbar,
|
||||
},
|
||||
meta: {
|
||||
title: 'Character Sheet',
|
||||
@@ -263,13 +248,10 @@ const router = routerFactory.create();
|
||||
router.beforeEach((to, from, next) => {
|
||||
let user = Meteor.user();
|
||||
if (
|
||||
to.path === '/countdown' ||
|
||||
to.path === '/sign-in' ||
|
||||
(user && user.roles && user.roles.includes('admin'))
|
||||
){
|
||||
next();
|
||||
} else if (new Date() < LAUNCH_DATE){
|
||||
next('/countdown');
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user