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 '/imports/api/sharing/sharing.js';
let SharingSchema = new SimpleSchema({
owner: {
@@ -28,7 +29,7 @@ let SharingSchema = new SimpleSchema({
},
public: {
type: Boolean,
optional: true,
defaultValue: false,
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(),
run({usernameOrEmail}){
let user = Accounts.findUserByUsername(username) ||
Accounts.findUserByEmail(email);
if (Meteor.isClient) return;
let user = Accounts.findUserByUsername(usernameOrEmail) ||
Accounts.findUserByEmail(usernameOrEmail);
return user && user._id;
}
});

View File

@@ -71,7 +71,14 @@ export default {
this.loading = false;
this.dirty = false;
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){
this.dirty = true;

View File

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

View File

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

View File

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