Disabled various buttons when the user doesn't have edit permission

This commit is contained in:
Thaum Rystra
2020-05-21 12:47:02 +02:00
parent 47aad6d186
commit 13a0d66433
10 changed files with 303 additions and 189 deletions

View File

@@ -5,6 +5,7 @@
:value="model.name" :value="model.name"
:error-messages="errors.name" :error-messages="errors.name"
:debounce-time="debounceTime" :debounce-time="debounceTime"
:disabled="disabled"
@change="(value, ack) => $emit('change', {path: ['name'], value, ack})" @change="(value, ack) => $emit('change', {path: ['name'], value, ack})"
/> />
<text-field <text-field
@@ -12,6 +13,7 @@
:value="model.alignment" :value="model.alignment"
:error-messages="errors.alignment" :error-messages="errors.alignment"
:debounce-time="debounceTime" :debounce-time="debounceTime"
:disabled="disabled"
@change="(value, ack) => $emit('change', {path: ['alignment'], value, ack})" @change="(value, ack) => $emit('change', {path: ['alignment'], value, ack})"
/> />
<text-field <text-field
@@ -19,6 +21,7 @@
:value="model.gender" :value="model.gender"
:error-messages="errors.gender" :error-messages="errors.gender"
:debounce-time="debounceTime" :debounce-time="debounceTime"
:disabled="disabled"
@change="(value, ack) => $emit('change', {path: ['gender'], value, ack})" @change="(value, ack) => $emit('change', {path: ['gender'], value, ack})"
/> />
<text-field <text-field
@@ -27,6 +30,7 @@
:value="model.picture" :value="model.picture"
:error-messages="errors.picture" :error-messages="errors.picture"
:debounce-time="debounceTime" :debounce-time="debounceTime"
:disabled="disabled"
@change="(value, ack) => $emit('change', {path: ['picture'], value, ack})" @change="(value, ack) => $emit('change', {path: ['picture'], value, ack})"
/> />
<text-field <text-field
@@ -35,6 +39,7 @@
:value="model.avatarPicture" :value="model.avatarPicture"
:error-messages="errors.avatarPicture" :error-messages="errors.avatarPicture"
:debounce-time="debounceTime" :debounce-time="debounceTime"
:disabled="disabled"
@change="(value, ack) => $emit('change', {path: ['avatarPicture'], value, ack})" @change="(value, ack) => $emit('change', {path: ['avatarPicture'], value, ack})"
/> />
<!-- <!--
@@ -44,18 +49,21 @@
label="Use variant encumbrance" label="Use variant encumbrance"
:input-value="model.settings.useVariantEncumbrance" :input-value="model.settings.useVariantEncumbrance"
:error-messages="errors.useVariantEncumbrance" :error-messages="errors.useVariantEncumbrance"
:disabled="disabled"
@change="value => $emit('change', {path: ['settings','useVariantEncumbrance'], value})" @change="value => $emit('change', {path: ['settings','useVariantEncumbrance'], value})"
/> />
<v-switch <v-switch
label="Hide spells tab" label="Hide spells tab"
:input-value="model.settings.hideSpellcasting" :input-value="model.settings.hideSpellcasting"
:error-messages="errors.hideSpellcasting" :error-messages="errors.hideSpellcasting"
:disabled="disabled"
@change="value => $emit('change', {path: ['settings','hideSpellcasting'], value})" @change="value => $emit('change', {path: ['settings','hideSpellcasting'], value})"
/> />
<v-switch <v-switch
label="Swap ability scores and modifiers" label="Swap ability scores and modifiers"
:input-value="model.settings.swapStatAndModifier" :input-value="model.settings.swapStatAndModifier"
:error-messages="errors.swapStatAndModifier" :error-messages="errors.swapStatAndModifier"
:disabled="disabled"
@change="value => $emit('change', {path: ['settings','swapStatAndModifier'], value})" @change="value => $emit('change', {path: ['settings','swapStatAndModifier'], value})"
/> />
</form-section> </form-section>
@@ -88,6 +96,7 @@ export default {
type: Boolean, type: Boolean,
}, },
debounceTime: Number, debounceTime: Number,
disabled: Boolean,
}, },
}; };
</script> </script>

View File

@@ -6,6 +6,7 @@
<div> <div>
<creature-form <creature-form
:model="model" :model="model"
:disabled="editPermission === false"
@change="change" @change="change"
/> />
</div> </div>
@@ -25,6 +26,7 @@ import Creatures from '/imports/api/creature/Creatures.js';
import {updateCreature} from '/imports/api/creature/Creatures.js'; import {updateCreature} from '/imports/api/creature/Creatures.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue'; import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
import CreatureForm from '/imports/ui/creature/CreatureForm.vue' import CreatureForm from '/imports/ui/creature/CreatureForm.vue'
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
export default { export default {
components: { components: {
@@ -39,6 +41,14 @@ export default {
model(){ model(){
return Creatures.findOne(this._id); return Creatures.findOne(this._id);
}, },
editPermission(){
try {
assertEditPermission(this.model, Meteor.userId());
return true;
} catch (e) {
return false;
}
},
}, },
methods: { methods: {
change({path, value, ack}){ change({path, value, ack}){

View File

@@ -48,17 +48,13 @@
//TODO add a "no character found" screen if shown on a false address //TODO add a "no character found" screen if shown on a false address
// or on a character the user does not have permission to view // or on a character the user does not have permission to view
import Creatures from '/imports/api/creature/Creatures.js'; import Creatures from '/imports/api/creature/Creatures.js';
import removeCreature from '/imports/api/creature/removeCreature.js';
import isDarkColor from '/imports/ui/utility/isDarkColor.js';
import { mapMutations } from 'vuex';
import { theme } from '/imports/ui/theme.js';
import StatsTab from '/imports/ui/creature/character/characterSheetTabs/StatsTab.vue'; import StatsTab from '/imports/ui/creature/character/characterSheetTabs/StatsTab.vue';
import FeaturesTab from '/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue'; import FeaturesTab from '/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue';
import InventoryTab from '/imports/ui/creature/character/characterSheetTabs/InventoryTab.vue'; import InventoryTab from '/imports/ui/creature/character/characterSheetTabs/InventoryTab.vue';
import SpellsTab from '/imports/ui/creature/character/characterSheetTabs/SpellsTab.vue'; import SpellsTab from '/imports/ui/creature/character/characterSheetTabs/SpellsTab.vue';
import PersonaTab from '/imports/ui/creature/character/characterSheetTabs/PersonaTab.vue'; import PersonaTab from '/imports/ui/creature/character/characterSheetTabs/PersonaTab.vue';
import TreeTab from '/imports/ui/creature/character/characterSheetTabs/TreeTab.vue'; import TreeTab from '/imports/ui/creature/character/characterSheetTabs/TreeTab.vue';
import { recomputeCreature } from '/imports/api/creature/computation/recomputeCreature.js'; import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
export default { export default {
components: { components: {
@@ -81,7 +77,7 @@
}, },
reactiveProvide: { reactiveProvide: {
name: 'context', name: 'context',
include: ['creature'], include: ['creature', 'editPermission'],
}, },
onMounted(){ onMounted(){
this.$store.commit('setPageTitle', this.creature && this.creature.name || 'Character Sheet'); this.$store.commit('setPageTitle', this.creature && this.creature.name || 'Character Sheet');
@@ -100,6 +96,14 @@
creature(){ creature(){
return Creatures.findOne(this.creatureId) || {}; return Creatures.findOne(this.creatureId) || {};
}, },
editPermission(){
try {
assertEditPermission(this.creature, Meteor.userId());
return true;
} catch (e) {
return false;
}
},
}, },
} }
</script> </script>

View File

@@ -5,6 +5,7 @@
<toolbar-card color=""> <toolbar-card color="">
<v-spacer slot="toolbar" /> <v-spacer slot="toolbar" />
<v-switch <v-switch
v-if="context.editPermission !== false"
slot="toolbar" slot="toolbar"
v-model="organize" v-model="organize"
label="Organize" label="Organize"
@@ -53,6 +54,9 @@ export default {
ContainerCard, ContainerCard,
ToolbarCard, ToolbarCard,
}, },
inject: {
context: { default: {} }
},
props: { props: {
creatureId: String, creatureId: String,
}, },

View File

@@ -5,6 +5,7 @@
<v-card> <v-card>
<v-card-text> <v-card-text>
<v-switch <v-switch
v-if="context.editPermission !== false"
v-model="organize" v-model="organize"
label="Organize" label="Organize"
class="justify-end" class="justify-end"
@@ -48,6 +49,9 @@ export default {
CreaturePropertiesTree, CreaturePropertiesTree,
SpellListCard, SpellListCard,
}, },
inject: {
context: { default: {} }
},
props: { props: {
creatureId: { creatureId: {
type: String, type: String,

View File

@@ -21,6 +21,7 @@
> >
<v-spacer /> <v-spacer />
<v-switch <v-switch
v-if="context.editPermission !== false"
v-model="organize" v-model="organize"
label="Organize" label="Organize"
class="mx-3" class="mx-3"
@@ -153,6 +154,9 @@
PropertyIcon, PropertyIcon,
LabeledFab, LabeledFab,
}, },
inject: {
context: { default: {} }
},
props: { props: {
creatureId: { creatureId: {
type: String, type: String,

View File

@@ -21,17 +21,16 @@
<v-layout <v-layout
column column
align-center align-center
@click="edit"
style="cursor: pointer;" style="cursor: pointer;"
class="bar" class="bar"
@click="edit"
> >
<v-progress-linear <v-progress-linear
:value="(value / maxValue) * 100" :value="(value / maxValue) * 100"
height="20" height="20"
color="green lighten-1" color="green lighten-1"
class="ma-0" class="ma-0"
> />
</v-progress-linear>
<span <span
class="value" class="value"
style="margin-top: -20px; z-index: 1; font-size: 15px; font-weight: 600; height: 20px;" style="margin-top: -20px; z-index: 1; font-size: 15px; font-weight: 600; height: 20px;"
@@ -50,40 +49,53 @@
<v-spacer /> <v-spacer />
<v-btn-toggle <v-btn-toggle
:value="operation === 'add' ? 0: operation === 'subtract' ? 1 : null" :value="operation === 'add' ? 0: operation === 'subtract' ? 1 : null"
@click="$refs.editInput.focus()"
class="mr-2" class="mr-2"
@click="$refs.editInput.focus()"
> >
<v-btn <v-btn
@click="toggleAdd(); $nextTick(() => $refs.editInput.focus())" :disabled="context.editPermission === false"
class="filled" class="filled"
@click="toggleAdd(); $nextTick(() => $refs.editInput.focus())"
> >
<v-icon>add</v-icon> <v-icon>add</v-icon>
</v-btn> </v-btn>
<v-btn <v-btn
@click="toggleSubtract(); $nextTick(() => $refs.editInput.focus())" :disabled="context.editPermission === false"
class="filled" class="filled"
@click="toggleSubtract(); $nextTick(() => $refs.editInput.focus())"
> >
<v-icon>remove</v-icon> <v-icon>remove</v-icon>
</v-btn> </v-btn>
</v-btn-toggle> </v-btn-toggle>
<v-text-field <v-text-field
v-if="editing"
ref="editInput"
solo solo
hide-details hide-details
type="number" type="number"
v-if="editing"
ref="editInput"
style="max-width: 120px;" style="max-width: 120px;"
min="0" min="0"
:value="editValue" :value="editValue"
:prepend-inner-icon="operationIcon(operation)" :prepend-inner-icon="operationIcon(operation)"
:disabled="context.editPermission === false"
@focus="$event.target.select()" @focus="$event.target.select()"
@keypress="keypress" @keypress="keypress"
/>
<v-btn
small
fab
class="filled"
color="red"
@click="commitEdit"
> >
</v-text-field>
<v-btn small fab @click="commitEdit" class="filled" color="red">
<v-icon>done</v-icon> <v-icon>done</v-icon>
</v-btn> </v-btn>
<v-btn small fab @click="cancelEdit" class="mx-0 filled"> <v-btn
small
fab
class="mx-0 filled"
@click="cancelEdit"
>
<v-icon>close</v-icon> <v-icon>close</v-icon>
</v-btn> </v-btn>
<v-spacer /> <v-spacer />
@@ -91,13 +103,26 @@
</transition> </transition>
</v-flex> </v-flex>
<transition name="background-transition"> <transition name="background-transition">
<div v-if="editing" class="page-tint" @click="cancelEdit" /> <div
v-if="editing"
class="page-tint"
@click="cancelEdit"
/>
</transition> </transition>
</v-layout> </v-layout>
</template> </template>
<script> <script>
export default { export default {
inject: {
context: { default: {} }
},
props: {
value: Number,
maxValue: Number,
name: String,
_id: String,
},
data() { data() {
return { return {
editing: false, editing: false,
@@ -106,12 +131,6 @@
hover: false, hover: false,
}; };
}, },
props: {
value: Number,
maxValue: Number,
name: String,
_id: String,
},
methods: { methods: {
edit() { edit() {
this.editing = true; this.editing = true;

View File

@@ -17,7 +17,7 @@
<v-btn <v-btn
icon icon
small small
:disabled="currentValue >= model.value" :disabled="currentValue >= model.value || context.editPermission === false"
@click="increment(1)" @click="increment(1)"
> >
<v-icon>arrow_drop_up</v-icon> <v-icon>arrow_drop_up</v-icon>
@@ -25,7 +25,7 @@
<v-btn <v-btn
icon icon
small small
:disabled="currentValue <= 0" :disabled="currentValue <= 0 || context.editPermission === false"
@click="increment(-1)" @click="increment(-1)"
> >
<v-icon>arrow_drop_down</v-icon> <v-icon>arrow_drop_down</v-icon>
@@ -68,6 +68,9 @@ import ComputedForCreature from '/imports/ui/components/computation/ComputedForC
export default { export default {
components: { components: {
Computed: ComputedForCreature, Computed: ComputedForCreature,
},
inject: {
context: { default: {} }
}, },
props: { props: {
model: { model: {

View File

@@ -1,18 +1,35 @@
<template lang="html"> <template lang="html">
<v-card class="resource-card layout row" :class="hover ? 'elevation-8': ''"> <v-card
class="resource-card layout row"
:class="hover ? 'elevation-8': ''"
>
<div class="buttons layout column justify-center pl-3"> <div class="buttons layout column justify-center pl-3">
<v-btn icon small :disabled="currentValue >= value" @click="increment(1)"> <v-btn
icon
small
:disabled="currentValue >= value || context.editPermission === false"
@click="increment(1)"
>
<v-icon>arrow_drop_up</v-icon> <v-icon>arrow_drop_up</v-icon>
</v-btn> </v-btn>
<v-btn icon small :disabled="currentValue <= 0" @click="increment(-1)"> <v-btn
icon
small
:disabled="currentValue <= 0 || context.editPermission === false"
@click="increment(-1)"
>
<v-icon>arrow_drop_down</v-icon> <v-icon>arrow_drop_down</v-icon>
</v-btn> </v-btn>
</div> </div>
<div <div
class="layout row align-center value pl-2 pr-3" class="layout row align-center value pl-2 pr-3"
> >
<div class="display-1">{{currentValue}}</div> <div class="display-1">
<div class="title ml-2 max-value">/{{value}}</div> {{ currentValue }}
</div>
<div class="title ml-2 max-value">
/{{ value }}
</div>
</div> </div>
<div <div
class="content layout row align-center pr-3" class="content layout row align-center pr-3"
@@ -29,15 +46,18 @@
<script> <script>
export default { export default {
data(){ return{
hover: false,
}},
props: { props: {
_id: String, _id: String,
name: String, name: String,
color: String, color: String,
value: Number, value: Number,
damage: Number, damage: Number,
},
data(){ return{
hover: false,
}},
inject: {
context: { default: {} }
}, },
computed: { computed: {
currentValue(){ currentValue(){

View File

@@ -1,40 +1,74 @@
<template lang="html"> <template lang="html">
<v-list-tile class="spell-slot-list-tile" :class="{hover}"> <v-list-tile
class="spell-slot-list-tile"
:class="{hover}"
>
<v-list-tile-action> <v-list-tile-action>
<div
<div class="layout row align-center" v-if="value > 4"> v-if="value > 4"
class="layout row align-center"
>
<div class="buttons layout column justify-center"> <div class="buttons layout column justify-center">
<v-btn icon small :disabled="currentValue >= value" @click="increment(1)">
<v-icon>arrow_drop_up</v-icon>
</v-btn>
<v-btn icon small :disabled="currentValue <= 0" @click="increment(-1)">
<v-icon>arrow_drop_down</v-icon>
</v-btn>
</div>
<div class="layout row value" style="align-items: baseline;">
<div class="display-1">{{currentValue}}</div>
<div class="title ml-2 max-value">/{{value}}</div>
</div>
</div>
<div class="layout row align-center justify-end slot-buttons" v-else>
<v-btn <v-btn
icon icon
small small
:disabled="
currentValue >= value ||
context.editPermission === false
"
@click="increment(1)"
>
<v-icon>arrow_drop_up</v-icon>
</v-btn>
<v-btn
icon
small
:disabled="
currentValue <= 0 ||
context.editPermission === false
"
@click="increment(-1)"
>
<v-icon>arrow_drop_down</v-icon>
</v-btn>
</div>
<div
class="layout row value"
style="align-items: baseline;"
>
<div class="display-1">
{{ currentValue }}
</div>
<div class="title ml-2 max-value">
/{{ value }}
</div>
</div>
</div>
<div
v-else
class="layout row align-center justify-end slot-buttons"
>
<v-btn
v-for="i in value" v-for="i in value"
:disabled="!(i === currentValue || i === currentValue + 1)"
:key="i" :key="i"
icon
small
:disabled="
!(i === currentValue || i === currentValue + 1) ||
context.editPermission === false
"
@click="increment(i > currentValue ? 1 : -1)" @click="increment(i > currentValue ? 1 : -1)"
> >
<v-icon>{{ <v-icon>
{{
i > currentValue ? i > currentValue ?
'radio_button_unchecked' : 'radio_button_unchecked' :
'radio_button_checked' 'radio_button_checked'
}}</v-icon> }}
</v-icon>
</v-btn> </v-btn>
</div> </div>
</v-list-tile-action> </v-list-tile-action>
<v-list-tile-content <v-list-tile-content
@@ -53,9 +87,6 @@
<script> <script>
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
export default { export default {
data(){ return{
hover: false,
}},
props: { props: {
_id: String, _id: String,
name: String, name: String,
@@ -65,6 +96,12 @@ export default {
type: Number, type: Number,
default: 0, default: 0,
}, },
},
data(){ return{
hover: false,
}},
inject: {
context: { default: {} }
}, },
computed: { computed: {
currentValue(){ currentValue(){