Made owner of sheets and libraries more visible

This commit is contained in:
Stefan Zermatten
2023-06-21 13:00:07 +02:00
parent 77ae2d9de8
commit b42a873a5f
6 changed files with 185 additions and 40 deletions

View File

@@ -2,18 +2,21 @@
<div class="creature-form"> <div class="creature-form">
<text-field <text-field
label="Name" label="Name"
:disabled="!editPermission"
:value="model.name" :value="model.name"
:error-messages="errors.name" :error-messages="errors.name"
@change="(value, ack) => $emit('change', {path: ['name'], value, ack})" @change="(value, ack) => $emit('change', {path: ['name'], value, ack})"
/> />
<text-field <text-field
label="Alignment" label="Alignment"
:disabled="!editPermission"
:value="model.alignment" :value="model.alignment"
:error-messages="errors.alignment" :error-messages="errors.alignment"
@change="(value, ack) => $emit('change', {path: ['alignment'], value, ack})" @change="(value, ack) => $emit('change', {path: ['alignment'], value, ack})"
/> />
<text-field <text-field
label="Gender" label="Gender"
:disabled="!editPermission"
:value="model.gender" :value="model.gender"
:error-messages="errors.gender" :error-messages="errors.gender"
@change="(value, ack) => $emit('change', {path: ['gender'], value, ack})" @change="(value, ack) => $emit('change', {path: ['gender'], value, ack})"
@@ -21,6 +24,7 @@
<text-field <text-field
label="Picture URL" label="Picture URL"
hint="A link to a high resolution image" hint="A link to a high resolution image"
:disabled="!editPermission"
:value="model.picture" :value="model.picture"
:error-messages="errors.picture" :error-messages="errors.picture"
@change="(value, ack) => $emit('change', {path: ['picture'], value, ack})" @change="(value, ack) => $emit('change', {path: ['picture'], value, ack})"
@@ -28,6 +32,7 @@
<text-field <text-field
label="Avatar picture URL" label="Avatar picture URL"
hint="A link to a smaller, square image to use as an avatar" hint="A link to a smaller, square image to use as an avatar"
:disabled="!editPermission"
:value="model.avatarPicture" :value="model.avatarPicture"
:error-messages="errors.avatarPicture" :error-messages="errors.avatarPicture"
@change="(value, ack) => $emit('change', {path: ['avatarPicture'], value, ack})" @change="(value, ack) => $emit('change', {path: ['avatarPicture'], value, ack})"
@@ -36,21 +41,25 @@
<form-section name="Settings"> <form-section name="Settings">
<v-switch <v-switch
label="Hide redundant stats" label="Hide redundant stats"
:disabled="!editPermission"
:input-value="model.settings.hideUnusedStats" :input-value="model.settings.hideUnusedStats"
@change="value => $emit('change', {path: ['settings','hideUnusedStats'], value: !!value})" @change="value => $emit('change', {path: ['settings','hideUnusedStats'], value: !!value})"
/> />
<v-switch <v-switch
label="Hide rest buttons" label="Hide rest buttons"
:disabled="!editPermission"
:input-value="model.settings.hideRestButtons" :input-value="model.settings.hideRestButtons"
@change="value => $emit('change', {path: ['settings','hideRestButtons'], value: !!value})" @change="value => $emit('change', {path: ['settings','hideRestButtons'], value: !!value})"
/> />
<v-switch <v-switch
label="Show spells tab" label="Show spells tab"
:disabled="!editPermission"
:input-value="!model.settings.hideSpellsTab" :input-value="!model.settings.hideSpellsTab"
@change="changeHideSpellsTab" @change="changeHideSpellsTab"
/> />
<v-switch <v-switch
label="Show tree tab" label="Show tree tab"
:disabled="!editPermission"
:input-value="model.settings.showTreeTab" :input-value="model.settings.showTreeTab"
@change="changeShowTreeTab" @change="changeShowTreeTab"
/> />
@@ -62,6 +71,7 @@
min="0" min="0"
max="1" max="1"
step="0.1" step="0.1"
:disabled="!editPermission"
:value="model.settings.hitDiceResetMultiplier" :value="model.settings.hitDiceResetMultiplier"
@change="(value, ack) => $emit('change', {path: ['settings','hitDiceResetMultiplier'], value, ack})" @change="(value, ack) => $emit('change', {path: ['settings','hitDiceResetMultiplier'], value, ack})"
/> />
@@ -69,6 +79,7 @@
label="Discord Webhook URL" label="Discord Webhook URL"
hint="This creature's logs will be posted to the discord channel" hint="This creature's logs will be posted to the discord channel"
placeholder="https://discordapp.com/api/webhooks/<id>/<token>" placeholder="https://discordapp.com/api/webhooks/<id>/<token>"
:disabled="!editPermission"
:value="model.settings.discordWebhook" :value="model.settings.discordWebhook"
@change="(value, ack) => $emit('change', {path: ['settings','discordWebhook'], value, ack})" @change="(value, ack) => $emit('change', {path: ['settings','discordWebhook'], value, ack})"
/> />
@@ -96,12 +107,13 @@
<form-section name="Libraries"> <form-section name="Libraries">
<smart-switch <smart-switch
label="All user libraries" label="All user libraries"
:disabled="!editPermission"
:value="allUserLibraries" :value="allUserLibraries"
@change="allUserLibrariesChange" @change="allUserLibrariesChange"
/> />
<library-list <library-list
selection selection
:disabled="!model.allowedLibraries && !model.allowedLibraryCollections" :disabled="!editPermission || (!model.allowedLibraries && !model.allowedLibraryCollections)"
:libraries-selected="model.allowedLibraries" :libraries-selected="model.allowedLibraries"
:library-collections-selected="model.allowedLibraryCollections" :library-collections-selected="model.allowedLibraryCollections"
:libraries-selected-by-collections="librariesSelectedByCollections" :libraries-selected-by-collections="librariesSelectedByCollections"
@@ -142,6 +154,7 @@ import FormSection, { FormSections } from '/imports/client/ui/properties/forms/s
import LibraryList from '/imports/client/ui/library/LibraryList.vue'; import LibraryList from '/imports/client/ui/library/LibraryList.vue';
import LibraryCollections from '/imports/api/library/LibraryCollections.js'; import LibraryCollections from '/imports/api/library/LibraryCollections.js';
import { changeAllowedLibraries, toggleAllUserLibraries } from '/imports/api/creature/creatures/methods/changeAllowedLibraries.js'; import { changeAllowedLibraries, toggleAllUserLibraries } from '/imports/api/creature/creatures/methods/changeAllowedLibraries.js';
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
export default { export default {
components: { components: {
@@ -227,6 +240,14 @@ export default {
}); });
return ids; return ids;
}, },
editPermission() {
try {
assertEditPermission(this.model, Meteor.userId());
return true;
} catch (e) {
return false;
}
},
}, },
methods: { methods: {
changeShowTreeTab(value) { changeShowTreeTab(value) {

View File

@@ -29,10 +29,10 @@
bottom bottom
left left
transition="slide-y-transition" transition="slide-y-transition"
data-id="creature-menu"
> >
<template #activator="{ on }"> <template #activator="{ on }">
<v-btn <v-btn
data-id="creature-menu"
icon icon
v-on="on" v-on="on"
> >
@@ -40,6 +40,35 @@
</v-btn> </v-btn>
</template> </template>
<v-list> <v-list>
<v-list-item
v-if="!isOwner && ownerName"
two-line
disabled
>
<v-list-item-avatar>
<v-icon>
mdi-account
</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title>
{{ ownerName }}
</v-list-item-title>
<v-list-item-subtitle>
Sheet owner
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-list-item
v-if="!isOwner"
@click="unshareWithMe"
>
<v-list-item-title>
<v-icon left>
mdi-cancel
</v-icon> Unshare with me
</v-list-item-title>
</v-list-item>
<v-list-item :to="printUrl"> <v-list-item :to="printUrl">
<v-list-item-title> <v-list-item-title>
<v-icon left> <v-icon left>
@@ -47,37 +76,31 @@
</v-icon> Print </v-icon> Print
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
<template v-if="editPermission"> <v-list-item @click="showCharacterForm">
<v-list-item @click="deleteCharacter"> <v-list-item-title>
<v-list-item-title> <v-icon left>
<v-icon left> mdi-pencil
mdi-delete </v-icon> Edit details
</v-icon> Delete </v-list-item-title>
</v-list-item-title> </v-list-item>
</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-list-item
v-else :disabled="!isOwner"
@click="unshareWithMe" @click="showShareDialog"
>
<v-list-item-title>
<v-icon left>
mdi-share-variant
</v-icon> Sharing
</v-list-item-title>
</v-list-item>
<v-list-item
:disabled="!isOwner"
@click="deleteCharacter"
> >
<v-list-item-title> <v-list-item-title>
<v-icon left> <v-icon left>
mdi-delete mdi-delete
</v-icon> Unshare with me </v-icon> Delete
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
</v-list> </v-list>
@@ -266,6 +289,15 @@ export default {
return false; return false;
} }
}, },
isOwner() {
if (!this.creature) return;
return Meteor.userId() === this.creature.owner;
},
ownerName() {
if (!this.creature) return;
const username = Meteor.users.findOne(this.creature.owner)?.username;
return username;
},
}, },
} }
</script> </script>

View File

@@ -8,6 +8,7 @@
<v-btn <v-btn
icon icon
data-id="share-library-button" data-id="share-library-button"
:disabled="!isOwner"
@click="share" @click="share"
> >
<v-icon>mdi-share-variant</v-icon> <v-icon>mdi-share-variant</v-icon>
@@ -15,12 +16,32 @@
<v-btn <v-btn
icon icon
data-id="delete-library-button" data-id="delete-library-button"
:disabled="!isOwner"
@click="remove" @click="remove"
> >
<v-icon>mdi-delete</v-icon> <v-icon>mdi-delete</v-icon>
</v-btn> </v-btn>
</template> </template>
<template v-if="model"> <template v-if="model">
<v-list-item
v-if="!isOwner"
class="px-0"
two-line
>
<v-list-item-avatar>
<v-icon>
mdi-account
</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title>
{{ ownerName || '?' }}
</v-list-item-title>
<v-list-item-subtitle>
Collection owner
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<text-field <text-field
label="name" label="name"
:value="model.name" :value="model.name"
@@ -33,6 +54,7 @@
/> />
<smart-switch <smart-switch
:value="model.showInMarket" :value="model.showInMarket"
:disabled="!isOwner"
label="Show in community library browser" label="Show in community library browser"
@change="(showInMarket, ack) => updateLibraryCollection({showInMarket}, ack)" @change="(showInMarket, ack) => updateLibraryCollection({showInMarket}, ack)"
/> />
@@ -121,6 +143,9 @@ export default {
meteor: { meteor: {
'$subscribe': { '$subscribe': {
libraries: [], libraries: [],
libraryCollection() {
return [this._id]
},
}, },
model() { model() {
return LibraryCollections.findOne(this._id); return LibraryCollections.findOne(this._id);
@@ -144,6 +169,15 @@ export default {
}; };
}); });
}, },
isOwner() {
if (!this.model) return;
return Meteor.userId() === this.model.owner;
},
ownerName() {
if (!this.model) return;
const username = Meteor.users.findOne(this.model.owner)?.username;
return username;
},
} }
} }
</script> </script>

View File

@@ -8,6 +8,7 @@
<v-btn <v-btn
icon icon
data-id="share-library-button" data-id="share-library-button"
:disabled="!isOwner"
@click="share" @click="share"
> >
<v-icon>mdi-share-variant</v-icon> <v-icon>mdi-share-variant</v-icon>
@@ -15,12 +16,32 @@
<v-btn <v-btn
icon icon
data-id="delete-library-button" data-id="delete-library-button"
:disabled="!isOwner"
@click="remove" @click="remove"
> >
<v-icon>mdi-delete</v-icon> <v-icon>mdi-delete</v-icon>
</v-btn> </v-btn>
</template> </template>
<template v-if="model"> <template v-if="model">
<v-list-item
v-if="!isOwner && ownerName"
class="px-0"
two-line
>
<v-list-item-avatar>
<v-icon>
mdi-account
</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title>
{{ ownerName }}
</v-list-item-title>
<v-list-item-subtitle>
Library owner
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<text-field <text-field
label="name" label="name"
:value="model.name" :value="model.name"
@@ -33,6 +54,7 @@
/> />
<smart-switch <smart-switch
:value="model.showInMarket" :value="model.showInMarket"
:disabled="!isOwner"
label="Show in community library browser" label="Show in community library browser"
@change="updateShowInMarket" @change="updateShowInMarket"
/> />
@@ -170,7 +192,16 @@ export default {
}, { }, {
sort: { order: 1 }, sort: { order: 1 },
}); });
} },
isOwner() {
if (!this.model) return;
return Meteor.userId() === this.model.owner;
},
ownerName() {
if (!this.model) return;
const username = Meteor.users.findOne(this.model.owner)?.username;
return username;
},
} }
} }
</script> </script>

View File

@@ -82,7 +82,14 @@ Meteor.publish('libraryCollection', function (libraryCollectionId) {
}, { }, {
sort: { name: 1 } sort: { name: 1 }
}); });
return [libraryCollectionCursor, libraryCursor]; return [
libraryCollectionCursor,
libraryCursor,
Meteor.users.find(
libraryCollection.owner,
{ fields: { username: 1 } }
),
];
}); });
}); });
}) })
@@ -148,13 +155,21 @@ Meteor.publish('browseLibraries', function () {
showInMarket: true, showInMarket: true,
public: true, public: true,
}, { }, {
sort: { name: 1 } sort: {
subscriberCount: 1,
name: 1,
},
limit: 500,
}), }),
LibraryCollections.find({ LibraryCollections.find({
showInMarket: true, showInMarket: true,
public: true, public: true,
}, { }, {
sort: { name: 1 } sort: {
subscriberCount: 1,
name: 1
},
limit: 500,
}), }),
]; ];
}); });
@@ -169,9 +184,15 @@ Meteor.publish('library', function (libraryId) {
catch (e) { catch (e) {
return this.error(e); return this.error(e);
} }
return Libraries.find({ return [
_id: libraryId, Libraries.find({
}); _id: libraryId,
}),
Meteor.users.find(
library.owner,
{ fields: { username: 1 } }
),
];
}); });
}); });

View File

@@ -19,10 +19,10 @@ Meteor.publish('singleCharacter', function (creatureId) {
const self = this; const self = this;
try { try {
schema.validate({ creatureId }); schema.validate({ creatureId });
} catch (e){ } catch (e) {
this.error(e); this.error(e);
} }
this.autorun(function (computation){ this.autorun(function (computation) {
let userId = this.userId; let userId = this.userId;
let permissionCreature = Creatures.findOne({ let permissionCreature = Creatures.findOne({
_id: creatureId, _id: creatureId,
@@ -32,11 +32,11 @@ Meteor.publish('singleCharacter', function (creatureId) {
try { assertViewPermission(permissionCreature, userId) } try { assertViewPermission(permissionCreature, userId) }
catch (e) { return [] } catch (e) { return [] }
loadCreature(creatureId, self); loadCreature(creatureId, self);
if (permissionCreature.computeVersion !== VERSION && computation.firstRun){ if (permissionCreature.computeVersion !== VERSION && computation.firstRun) {
try { try {
computeCreature(creatureId) computeCreature(creatureId)
} }
catch(e){ console.error(e) } catch (e) { console.error(e) }
} }
return [ return [
Creatures.find({ Creatures.find({
@@ -52,7 +52,13 @@ Meteor.publish('singleCharacter', function (creatureId) {
creatureId, creatureId,
}, { }, {
limit: 20, limit: 20,
sort: {date: -1}, sort: { date: -1 },
}),
// Also publish the owner's username
Meteor.users.find(permissionCreature.owner, {
fields: {
username: 1,
},
}), }),
]; ];
}); });