Improved sharing dialog, setting a sheet as public now working

This commit is contained in:
Thaum Rystra
2020-03-03 17:00:05 +02:00
parent d0c8131d5f
commit 46a0e92402
7 changed files with 129 additions and 29 deletions

View File

@@ -1,4 +1,5 @@
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import '/imports/api/sharing/sharing.js';
let SharingSchema = new SimpleSchema({ let SharingSchema = new SimpleSchema({
owner: { owner: {
@@ -28,7 +29,7 @@ let SharingSchema = new SimpleSchema({
}, },
public: { public: {
type: Boolean, type: Boolean,
optional: true, defaultValue: false,
index: 1, index: 1,
}, },
}); });

View File

@@ -0,0 +1,20 @@
import SimpleSchema from 'simpl-schema';
import { assertOwnership } from '/imports/api/sharing/sharingPermissions.js';
import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js';
import getCollectionByName from '/imports/api/parenting/getCollectionByName.js';
import { RefSchema } from '/imports/api/parenting/ChildSchema.js';
const setPublic = new ValidatedMethod({
name: 'sharing.methods.setPublic',
validate: new SimpleSchema({
docRef: RefSchema,
public: { type: Boolean },
}).validator(),
run({docRef, public}){
let doc = fetchDocByRef(docRef);
assertOwnership(doc, this.userId);
getCollectionByName(docRef.collection).update(docRef.id, {$set: {public}});
},
});
export { setPublic };

View File

@@ -134,8 +134,9 @@ Meteor.users.findUserByUsernameOrEmail = new ValidatedMethod({
}, },
}).validator(), }).validator(),
run({usernameOrEmail}){ run({usernameOrEmail}){
let user = Accounts.findUserByUsername(username) || if (Meteor.isClient) return;
Accounts.findUserByEmail(email); let user = Accounts.findUserByUsername(usernameOrEmail) ||
Accounts.findUserByEmail(usernameOrEmail);
return user && user._id; return user && user._id;
} }
}); });

View File

@@ -71,7 +71,14 @@ export default {
this.loading = false; this.loading = false;
this.dirty = false; this.dirty = false;
this.error = !!error; this.error = !!error;
this.ackErrors = error || null; if (!error){
this.ackErrors = null;
} else if (typeof error === 'string'){
this.ackErrors = error;
} else {
this.ackErrors = 'Something went wrong'
console.error(error);
}
}, },
change(val){ change(val){
this.dirty = true; this.dirty = true;

View File

@@ -9,9 +9,30 @@
</v-btn> </v-btn>
<span>{{character.name}}</span> <span>{{character.name}}</span>
<v-spacer/> <v-spacer/>
<v-btn flat icon @click="showCharacterForm" data-id="character-form-button"> <v-menu bottom left transition="slide-y-transition" data-id="creature-menu">
<v-icon>more</v-icon> <template v-slot:activator="{ on }">
</v-btn> <v-btn icon v-on="on">
<v-icon>more_vert</v-icon>
</v-btn>
</template>
<v-list>
<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-menu>
<v-tabs <v-tabs
slot="extension" slot="extension"
v-model="tab" v-model="tab"
@@ -81,12 +102,27 @@
showCharacterForm(){ showCharacterForm(){
this.$store.commit('pushDialogStack', { this.$store.commit('pushDialogStack', {
component: 'creature-form-dialog', component: 'creature-form-dialog',
elementId: 'character-form-button', elementId: 'creature-menu',
data: { data: {
_id: this.creatureId, _id: this.creatureId,
}, },
}); });
}, },
showShareDialog(){
this.$store.commit('pushDialogStack', {
component: 'share-dialog',
elementId: 'creature-menu',
data: {
docRef: {
id: this.creatureId,
collection: 'creatures',
}
},
});
},
deleteCharacter(){
console.log('todo');
},
isDarkColor, isDarkColor,
}, },
meteor: { meteor: {

View File

@@ -10,6 +10,7 @@ import FeatureDialogContainer from '/imports/ui/properties/features/FeatureDialo
import LibraryCreationDialog from '/imports/ui/library/LibraryCreationDialog.vue'; import LibraryCreationDialog from '/imports/ui/library/LibraryCreationDialog.vue';
import LibraryNodeCreationDialog from '/imports/ui/library/LibraryNodeCreationDialog.vue'; import LibraryNodeCreationDialog from '/imports/ui/library/LibraryNodeCreationDialog.vue';
import LibraryNodeEditDialog from '/imports/ui/library/LibraryNodeEditDialog.vue'; import LibraryNodeEditDialog from '/imports/ui/library/LibraryNodeEditDialog.vue';
import ShareDialog from '/imports/ui/sharing/ShareDialog.vue';
import SkillDialogContainer from '/imports/ui/properties/skills/SkillDialogContainer.vue'; import SkillDialogContainer from '/imports/ui/properties/skills/SkillDialogContainer.vue';
export default { export default {
@@ -25,5 +26,6 @@ export default {
LibraryCreationDialog, LibraryCreationDialog,
LibraryNodeCreationDialog, LibraryNodeCreationDialog,
LibraryNodeEditDialog, LibraryNodeEditDialog,
ShareDialog,
SkillDialogContainer, SkillDialogContainer,
}; };

View File

@@ -1,40 +1,40 @@
<template lang="html"> <template lang="html">
<dialog-base> <dialog-base>
<div slot="toolbar"> <div slot="toolbar">
Sharing {{name}} Sharing
</div> </div>
<div> <div v-if="model">
<smart-select <smart-select
label="Who can view" label="Who can view"
:items="[ :items="[
{text: 'Only people I share with', value: false}, {text: 'Only people I share with', value: 'false'},
{text: 'Anyone with link', value: true} {text: 'Anyone with link', value: 'true'}
]" ]"
:value="model.public" :value="!!model.public + ''"
:error-messages="errors.public"
@change="(value, ack) => setSheetPublic({value, ack})" @change="(value, ack) => setSheetPublic({value, ack})"
/> />
<div class="layout row"> <div class="layout row">
<text-field <text-field
label="Username or email" label="Username or email"
:value="userSearched"
@change="(value, ack) => getUser({value, ack})" @change="(value, ack) => getUser({value, ack})"
:debounceTime="300" :debounceTime="300"
/> />
<v-btn :disabled="userFoundState !== found"> <v-btn :disabled="userFoundState !== 'found'">
Share Share
</v-btn> </v-btn>
</div> </div>
<div class="sharedWith"> <div class="sharedWith">
<h3>Can Edit</h3> <h3 v-if="writers.length">Can Edit</h3>
<div v-for="userId in model.writers"> <div v-for="user in writers">
{{username(userId)}} {{user}}
<v-btn flat icon> <v-btn flat icon>
<v-icon>delete</v-icon> <v-icon>delete</v-icon>
</v-btn> </v-btn>
</div> </div>
<h3>Can View</h3> <h3 v-if="readers.length">Can View</h3>
<div v-for="userId in model.readers"> <div v-for="user in readers">
{{username(userId)}} {{user}}
<v-btn flat icon> <v-btn flat icon>
<v-icon>delete</v-icon> <v-icon>delete</v-icon>
</v-btn> </v-btn>
@@ -45,21 +45,38 @@
</template> </template>
<script> <script>
import { setPublic } from '/imports/api/sharing/sharing.js';
import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js'; import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js';
import DialogBase from '/imports/ui/dialogStack/DialogBase.vue'; import DialogBase from '/imports/ui/dialogStack/DialogBase.vue';
export default { export default {
components: { components: {
DialogBase, DialogBase,
}, },
data(){ return { data(){ return {
userSearched: undefined,
userFoundState: 'idle', userFoundState: 'idle',
userId: undefined, userId: undefined,
}}, }},
props: { props: {
ref: Object, docRef: Object,
}, },
methods: { methods: {
setSheetPublic({value, ack}){
setPublic.call({
docRef: this.docRef,
public: value === 'true',
}, (error, value) => {
ack(error && error.reason || error);
});
},
getUser({value, ack}){ getUser({value, ack}){
this.userSearched = value;
if (!value){
this.userFoundState = 'idle';
ack();
return;
}
Meteor.users.findUserByUsernameOrEmail.call({ Meteor.users.findUserByUsernameOrEmail.call({
usernameOrEmail: value usernameOrEmail: value
}, (error, result) => { }, (error, result) => {
@@ -69,8 +86,13 @@ export default {
} else { } else {
this.userId = result; this.userId = result;
if (result){ if (result){
this.userFoundState = 'found'; if (result === this.model.owner){
ack(); this.userFoundState = 'failed';
ack('User is already the owner')
} else {
this.userFoundState = 'found';
ack();
}
} else { } else {
this.userFoundState = 'notFound'; this.userFoundState = 'notFound';
ack('User not found'); ack('User not found');
@@ -81,15 +103,26 @@ export default {
}, },
meteor: { meteor: {
model(){ model(){
return fetchDocByRef(this.ref); if (!this.docRef || !this.docRef.id) return;
let model = fetchDocByRef(this.docRef);
console.log({model})
return model;
}, },
username(userId){ readers(){
let user = Meteor.users.findOne(userId); if (this.model){
return user && user.username; return Meteor.users.find({_id: {$in: this.model.readers}})
}
},
writers(){
if (this.model){
return Meteor.users.find({_id: {$in: this.model.writers}})
}
}, },
$subscribe: { $subscribe: {
'userPublicProfiles'(){ 'userPublicProfiles'(){
return [...this.model.writers, ...this.model.readers]; let model = this.model;
if (!model) return false;
return [model.owner, ...model.writers, ...model.readers];
}, },
}, },
}, },