Subscriptions and notifications for namespaces, tasks and lists (#410)
Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/410 Co-authored-by: konrad <konrad@kola-entertainments.de> Co-committed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
@ -54,6 +54,14 @@
|
||||
>
|
||||
Archive
|
||||
</dropdown-item>
|
||||
<task-subscription
|
||||
class="dropdown-item has-no-shadow"
|
||||
:is-button="false"
|
||||
entity="list"
|
||||
:entity-id="list.id"
|
||||
:subscription="subscription"
|
||||
@change="sub => subscription = sub"
|
||||
/>
|
||||
<dropdown-item
|
||||
:to="{ name: `${listRoutePrefix}.settings.delete`, params: { listId: list.id } }"
|
||||
icon="trash-alt"
|
||||
@ -69,10 +77,17 @@
|
||||
import {getSavedFilterIdFromListId} from '@/helpers/savedFilter'
|
||||
import Dropdown from '@/components/misc/dropdown'
|
||||
import DropdownItem from '@/components/misc/dropdown-item'
|
||||
import TaskSubscription from '@/components/misc/subscription'
|
||||
|
||||
export default {
|
||||
name: 'list-settings-dropdown',
|
||||
data() {
|
||||
return {
|
||||
subscription: null,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
TaskSubscription,
|
||||
DropdownItem,
|
||||
Dropdown,
|
||||
},
|
||||
@ -81,6 +96,9 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.subscription = this.list.subscription
|
||||
},
|
||||
computed: {
|
||||
backgroundsEnabled() {
|
||||
return this.$store.state.config.enabledBackgroundProviders.length > 0
|
||||
|
121
src/components/misc/subscription.vue
Normal file
121
src/components/misc/subscription.vue
Normal file
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<x-button
|
||||
type="secondary"
|
||||
:icon="icon"
|
||||
v-tooltip="tooltipText"
|
||||
@click="changeSubscription"
|
||||
:disabled="disabled"
|
||||
v-if="isButton"
|
||||
>
|
||||
{{ buttonText }}
|
||||
</x-button>
|
||||
<a
|
||||
v-tooltip="tooltipText"
|
||||
@click="changeSubscription"
|
||||
:class="{'is-disabled': disabled}"
|
||||
v-else
|
||||
>
|
||||
<span class="icon">
|
||||
<icon :icon="icon"/>
|
||||
</span>
|
||||
{{ buttonText }}
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SubscriptionService from '@/services/subscription'
|
||||
import SubscriptionModel from '@/models/subscription'
|
||||
|
||||
export default {
|
||||
name: 'task-subscription',
|
||||
data() {
|
||||
return {
|
||||
subscriptionService: SubscriptionService,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
entity: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
subscription: {
|
||||
required: true,
|
||||
},
|
||||
entityId: {
|
||||
required: true,
|
||||
},
|
||||
isButton: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.subscriptionService = new SubscriptionService()
|
||||
},
|
||||
computed: {
|
||||
tooltipText() {
|
||||
if(this.disabled) {
|
||||
return `You can't unsubscribe here because you are subscribed to this ${this.entity} through its ${this.subscription.entity}.`
|
||||
}
|
||||
|
||||
return this.subscription !== null ?
|
||||
`You are currently subscribed to this ${this.entity} and will receive notifications for changes.` :
|
||||
`You are not subscribed to this ${this.entity} and won't receive notifications for changes.`
|
||||
},
|
||||
buttonText() {
|
||||
return this.subscription !== null ? 'Unsubscribe' : 'Subscribe'
|
||||
},
|
||||
icon() {
|
||||
return this.subscription !== null ? ['far', 'bell-slash'] : 'bell'
|
||||
},
|
||||
disabled() {
|
||||
if (this.subscription === null) {
|
||||
return false
|
||||
}
|
||||
|
||||
return this.subscription.entity !== this.entity
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeSubscription() {
|
||||
if(this.disabled) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.subscription === null) {
|
||||
this.subscribe()
|
||||
} else {
|
||||
this.unsubscribe()
|
||||
}
|
||||
},
|
||||
subscribe() {
|
||||
const subscription = new SubscriptionModel({
|
||||
entity: this.entity,
|
||||
entityId: this.entityId,
|
||||
})
|
||||
this.subscriptionService.create(subscription)
|
||||
.then(() => {
|
||||
this.$emit('change', subscription)
|
||||
this.success({message: `You are now subscribed to this ${this.entity}`}, this)
|
||||
})
|
||||
.catch(e => {
|
||||
this.error(e, this)
|
||||
})
|
||||
},
|
||||
unsubscribe() {
|
||||
const subscription = new SubscriptionModel({
|
||||
entity: this.entity,
|
||||
entityId: this.entityId,
|
||||
})
|
||||
this.subscriptionService.delete(subscription)
|
||||
.then(() => {
|
||||
this.$emit('change', null)
|
||||
this.success({message: `You are now unsubscribed to this ${this.entity}`}, this)
|
||||
})
|
||||
.catch(e => {
|
||||
this.error(e, this)
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
@ -33,6 +33,14 @@
|
||||
>
|
||||
Archive
|
||||
</dropdown-item>
|
||||
<task-subscription
|
||||
class="dropdown-item has-no-shadow"
|
||||
:is-button="false"
|
||||
entity="namespace"
|
||||
:entity-id="namespace.id"
|
||||
:subscription="subscription"
|
||||
@change="sub => subscription = sub"
|
||||
/>
|
||||
<dropdown-item
|
||||
:to="{ name: 'namespace.settings.delete', params: { id: namespace.id } }"
|
||||
icon="trash-alt"
|
||||
@ -47,17 +55,27 @@
|
||||
<script>
|
||||
import Dropdown from '@/components/misc/dropdown'
|
||||
import DropdownItem from '@/components/misc/dropdown-item'
|
||||
import TaskSubscription from '@/components/misc/subscription'
|
||||
|
||||
export default {
|
||||
name: 'namespace-settings-dropdown',
|
||||
data() {
|
||||
return {
|
||||
subscription: null,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DropdownItem,
|
||||
Dropdown,
|
||||
TaskSubscription,
|
||||
},
|
||||
props: {
|
||||
namespace: {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.subscription = this.namespace.subscription
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user