feat: convert simple components to script setup and use typescript (#1120)
Co-authored-by: Dominik Pschenitschni <mail@celement.de> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/1120 Reviewed-by: konrad <k@knt.li> Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de> Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
This commit is contained in:
parent
f758eefa88
commit
ac630ac775
16 changed files with 298 additions and 387 deletions
|
@ -20,64 +20,59 @@
|
||||||
:class="{'is-favorite': list.isFavorite, 'is-archived': list.isArchived}"
|
:class="{'is-favorite': list.isFavorite, 'is-archived': list.isArchived}"
|
||||||
@click.stop="toggleFavoriteList(list)"
|
@click.stop="toggleFavoriteList(list)"
|
||||||
class="favorite">
|
class="favorite">
|
||||||
<icon icon="star" v-if="list.isFavorite"/>
|
<icon :icon="list.isFavorite ? 'star' : ['far', 'star']" />
|
||||||
<icon :icon="['far', 'star']" v-else/>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="title">{{ list.title }}</div>
|
<div class="title">{{ list.title }}</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
|
import {ref, watch} from 'vue'
|
||||||
|
import {useStore} from 'vuex'
|
||||||
|
|
||||||
import ListService from '@/services/list'
|
import ListService from '@/services/list'
|
||||||
|
|
||||||
export default {
|
const background = ref(null)
|
||||||
name: 'list-card',
|
const backgroundLoading = ref(false)
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
background: null,
|
|
||||||
backgroundLoading: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
list: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
showArchived: {
|
|
||||||
default: false,
|
|
||||||
type: Boolean,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
list: {
|
|
||||||
handler: 'loadBackground',
|
|
||||||
immediate: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async loadBackground() {
|
|
||||||
if (this.list === null || !this.list.backgroundInformation || this.backgroundLoading) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.backgroundLoading = true
|
const props = defineProps({
|
||||||
|
list: {
|
||||||
const listService = new ListService()
|
type: Object,
|
||||||
try {
|
required: true,
|
||||||
this.background = await listService.background(this.list)
|
|
||||||
} finally {
|
|
||||||
this.backgroundLoading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toggleFavoriteList(list) {
|
|
||||||
// The favorites pseudo list is always favorite
|
|
||||||
// Archived lists cannot be marked favorite
|
|
||||||
if (list.id === -1 || list.isArchived) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$store.dispatch('lists/toggleListFavorite', list)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
showArchived: {
|
||||||
|
default: false,
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(props.list, loadBackground, { immediate: true })
|
||||||
|
|
||||||
|
async function loadBackground() {
|
||||||
|
if (props.list === null || !props.list.backgroundInformation || backgroundLoading.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
backgroundLoading.value = true
|
||||||
|
|
||||||
|
const listService = new ListService()
|
||||||
|
try {
|
||||||
|
background.value = await listService.background(props.list)
|
||||||
|
} finally {
|
||||||
|
backgroundLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = useStore()
|
||||||
|
|
||||||
|
function toggleFavoriteList(list) {
|
||||||
|
// The favorites pseudo list is always favorite
|
||||||
|
// Archived lists cannot be marked favorite
|
||||||
|
if (list.id === -1 || list.isArchived) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
store.dispatch('lists/toggleListFavorite', list)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="isDone"
|
v-if="isDone"
|
||||||
class="is-done"
|
class="is-done"
|
||||||
:class="{ 'is-done--small': variant === variants.SMALL }"
|
:class="{ 'is-done--small': variant === 'small' }"
|
||||||
>
|
>
|
||||||
{{ $t('task.attributes.done') }}
|
{{ $t('task.attributes.done') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
const VARIANTS = {
|
import {PropType} from 'vue'
|
||||||
DEFAULT: 'default',
|
type Variants = 'default' | 'small'
|
||||||
SMALL: 'small',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
defineProps({
|
||||||
name: 'Done',
|
isDone: {
|
||||||
|
type: Boolean,
|
||||||
data() {
|
default: false,
|
||||||
return {
|
|
||||||
variants: VARIANTS,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
variant: {
|
||||||
props: {
|
type: String as PropType<Variants>,
|
||||||
isDone: {
|
default: 'default',
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
variant: {
|
|
||||||
type: String,
|
|
||||||
default: VARIANTS.DEFAULT,
|
|
||||||
validator: (variant) => Object.values(VARIANTS).includes(variant),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,41 +24,39 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
export default {
|
defineProps({
|
||||||
name: 'card',
|
title: {
|
||||||
props: {
|
type: String,
|
||||||
title: {
|
default: '',
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
padding: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
hasClose: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
closeIcon: {
|
|
||||||
type: String,
|
|
||||||
default: 'times',
|
|
||||||
},
|
|
||||||
shadow: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
hasContent: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
loading: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
emits: ['close'],
|
padding: {
|
||||||
}
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
hasClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
closeIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'times',
|
||||||
|
},
|
||||||
|
shadow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
hasContent: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
defineEmits(['close'])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -11,18 +11,15 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
export default {
|
defineProps({
|
||||||
name: 'dropdown-item',
|
to: {
|
||||||
props: {
|
required: true,
|
||||||
to: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
icon: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -7,16 +7,10 @@
|
||||||
</message>
|
</message>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
import Message from '@/components/misc/message'
|
import Message from '@/components/misc/message.vue'
|
||||||
|
|
||||||
export default {
|
function reload() {
|
||||||
name: 'error',
|
window.location.reload()
|
||||||
components: {Message},
|
|
||||||
methods: {
|
|
||||||
reload() {
|
|
||||||
window.location.reload()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -6,16 +6,14 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
import {mapState} from 'vuex'
|
import {computed} from 'vue'
|
||||||
|
import {useStore} from 'vuex'
|
||||||
|
|
||||||
export default {
|
const store = useStore()
|
||||||
name: 'legal',
|
|
||||||
computed: mapState({
|
const imprintUrl = computed(() => store.state.config.legal.imprintUrl)
|
||||||
imprintUrl: state => state.config.legal.imprintUrl,
|
const privacyPolicyUrl = computed(() => store.state.config.legal.privacyPolicyUrl)
|
||||||
privacyPolicyUrl: state => state.config.legal.privacyPolicyUrl,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -2,12 +2,6 @@
|
||||||
<div class="loader-container is-loading"></div>
|
<div class="loader-container is-loading"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'loading',
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.loader-container {
|
.loader-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script lang="ts" setup>
|
||||||
defineProps({
|
defineProps({
|
||||||
variant: {
|
variant: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
<div class="no-auth-wrapper">
|
<div class="no-auth-wrapper">
|
||||||
<div class="noauth-container">
|
<div class="noauth-container">
|
||||||
<Logo class="logo" width="400" height="117" />
|
<Logo class="logo" width="400" height="117" />
|
||||||
<message v-if="motd !== ''" class="my-2">
|
<Message v-if="motd !== ''" class="my-2">
|
||||||
{{ motd }}
|
{{ motd }}
|
||||||
</message>
|
</Message>
|
||||||
<slot/>
|
<slot/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script lang="ts" setup>
|
||||||
import Logo from '@/components/home/Logo.vue'
|
import Logo from '@/components/home/Logo.vue'
|
||||||
import message from '@/components/misc/message'
|
import Message from '@/components/misc/message.vue'
|
||||||
import {useStore} from 'vuex'
|
import {useStore} from 'vuex'
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,10 @@
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
function createPagination(totalPages, currentPage) {
|
import {computed} from 'vue'
|
||||||
|
|
||||||
|
function createPagination(totalPages: number, currentPage: number) {
|
||||||
const pages = []
|
const pages = []
|
||||||
for (let i = 0; i < totalPages; i++) {
|
for (let i = 0; i < totalPages; i++) {
|
||||||
|
|
||||||
|
@ -79,30 +81,18 @@ function getRouteForPagination(page = 1, type = 'list') {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: 'Pagination',
|
totalPages: {
|
||||||
|
type: Number,
|
||||||
props: {
|
required: true,
|
||||||
totalPages: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
currentPage: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
currentPage: {
|
||||||
computed: {
|
type: Number,
|
||||||
pages() {
|
default: 0,
|
||||||
return createPagination(this.totalPages, this.currentPage)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
|
||||||
methods: {
|
const pages = computed(() => createPagination(props.totalPages, props.currentPage))
|
||||||
getRouteForPagination,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<section v-else-if="error !== ''">
|
<section v-else-if="error !== ''">
|
||||||
<no-auth-wrapper>
|
<no-auth-wrapper>
|
||||||
<card>
|
<card>
|
||||||
<p v-if="error === errorNoApiUrl">
|
<p v-if="error === ERROR_NO_API_URL">
|
||||||
{{ $t('ready.noApiUrlConfigured') }}
|
{{ $t('ready.noApiUrlConfigured') }}
|
||||||
</p>
|
</p>
|
||||||
<message variant="danger" v-else>
|
<message variant="danger" v-else>
|
||||||
|
@ -40,51 +40,34 @@
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
|
import {ref, computed} from 'vue'
|
||||||
|
import {useStore} from 'vuex'
|
||||||
|
|
||||||
import Logo from '@/assets/logo.svg?component'
|
import Logo from '@/assets/logo.svg?component'
|
||||||
import ApiConfig from '@/components/misc/api-config'
|
import ApiConfig from '@/components/misc/api-config.vue'
|
||||||
import Message from '@/components/misc/message'
|
import Message from '@/components/misc/message.vue'
|
||||||
import NoAuthWrapper from '@/components/misc/no-auth-wrapper'
|
import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue'
|
||||||
import {mapState} from 'vuex'
|
|
||||||
import {ERROR_NO_API_URL} from '@/helpers/checkAndSetApiUrl'
|
import {ERROR_NO_API_URL} from '@/helpers/checkAndSetApiUrl'
|
||||||
|
|
||||||
export default {
|
const store = useStore()
|
||||||
name: 'ready',
|
|
||||||
components: {
|
const ready = computed(() => store.state.vikunjaReady)
|
||||||
Message,
|
const online = computed(() => store.state.online)
|
||||||
Logo,
|
|
||||||
NoAuthWrapper,
|
const error = ref('')
|
||||||
ApiConfig,
|
const showLoading = computed(() => !ready.value && error.value === '')
|
||||||
},
|
|
||||||
data() {
|
async function load() {
|
||||||
return {
|
try {
|
||||||
error: '',
|
await store.dispatch('loadApp')
|
||||||
errorNoApiUrl: ERROR_NO_API_URL,
|
} catch(e: any) {
|
||||||
}
|
error.value = e
|
||||||
},
|
}
|
||||||
created() {
|
|
||||||
this.load()
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
ready() {
|
|
||||||
return this.$store.state.vikunjaReady
|
|
||||||
},
|
|
||||||
showLoading() {
|
|
||||||
return !this.ready && this.error === ''
|
|
||||||
},
|
|
||||||
...mapState([
|
|
||||||
'online',
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
load() {
|
|
||||||
this.$store.dispatch('loadApp')
|
|
||||||
.catch(e => {
|
|
||||||
this.error = e
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -7,24 +7,21 @@
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
export default {
|
defineProps({
|
||||||
name: 'shortcut',
|
keys: {
|
||||||
props: {
|
type: Array,
|
||||||
keys: {
|
required: true,
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
combination: {
|
|
||||||
type: String,
|
|
||||||
default: '+',
|
|
||||||
},
|
|
||||||
is: {
|
|
||||||
type: String,
|
|
||||||
default: 'div',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
combination: {
|
||||||
|
type: String,
|
||||||
|
default: '+',
|
||||||
|
},
|
||||||
|
is: {
|
||||||
|
type: String,
|
||||||
|
default: 'div',
|
||||||
|
},
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -22,91 +22,89 @@
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
|
import {computed, shallowRef} from 'vue'
|
||||||
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import SubscriptionService from '@/services/subscription'
|
import SubscriptionService from '@/services/subscription'
|
||||||
import SubscriptionModel from '@/models/subscription'
|
import SubscriptionModel from '@/models/subscription'
|
||||||
|
|
||||||
export default {
|
import {success} from '@/message'
|
||||||
name: 'task-subscription',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
subscriptionService: new SubscriptionService(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
entity: {
|
|
||||||
required: true,
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
subscription: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
entityId: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
isButton: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ['change'],
|
|
||||||
computed: {
|
|
||||||
tooltipText() {
|
|
||||||
if (this.disabled) {
|
|
||||||
return this.$t('task.subscription.subscribedThroughParent', {
|
|
||||||
entity: this.entity,
|
|
||||||
parent: this.subscription.entity,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.subscription !== null ?
|
const props = defineProps({
|
||||||
this.$t('task.subscription.subscribed', {entity: this.entity}) :
|
entity: {
|
||||||
this.$t('task.subscription.notSubscribed', {entity: this.entity})
|
required: true,
|
||||||
},
|
type: String,
|
||||||
buttonText() {
|
|
||||||
return this.subscription !== null ? this.$t('task.subscription.unsubscribe') : this.$t('task.subscription.subscribe')
|
|
||||||
},
|
|
||||||
icon() {
|
|
||||||
return this.subscription !== null ? ['far', 'bell-slash'] : 'bell'
|
|
||||||
},
|
|
||||||
disabled() {
|
|
||||||
if (this.subscription === null) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.subscription.entity !== this.entity
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
subscription: {
|
||||||
changeSubscription() {
|
required: true,
|
||||||
if (this.disabled) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.subscription === null) {
|
|
||||||
this.subscribe()
|
|
||||||
} else {
|
|
||||||
this.unsubscribe()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async subscribe() {
|
|
||||||
const subscription = new SubscriptionModel({
|
|
||||||
entity: this.entity,
|
|
||||||
entityId: this.entityId,
|
|
||||||
})
|
|
||||||
await this.subscriptionService.create(subscription)
|
|
||||||
this.$emit('change', subscription)
|
|
||||||
this.$message.success({message: this.$t('task.subscription.subscribeSuccess', {entity: this.entity})})
|
|
||||||
},
|
|
||||||
async unsubscribe() {
|
|
||||||
const subscription = new SubscriptionModel({
|
|
||||||
entity: this.entity,
|
|
||||||
entityId: this.entityId,
|
|
||||||
})
|
|
||||||
await this.subscriptionService.delete(subscription)
|
|
||||||
this.$emit('change', null)
|
|
||||||
this.$message.success({message: this.$t('task.subscription.unsubscribeSuccess', {entity: this.entity})})
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
entityId: {
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
isButton: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['change'])
|
||||||
|
|
||||||
|
const subscriptionService = shallowRef(new SubscriptionService())
|
||||||
|
|
||||||
|
const {t} = useI18n()
|
||||||
|
const tooltipText = computed(() => {
|
||||||
|
if (disabled.value) {
|
||||||
|
return t('task.subscription.subscribedThroughParent', {
|
||||||
|
entity: props.entity,
|
||||||
|
parent: props.subscription.entity,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.subscription !== null ?
|
||||||
|
t('task.subscription.subscribed', {entity: props.entity}) :
|
||||||
|
t('task.subscription.notSubscribed', {entity: props.entity})
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttonText = computed(() => props.subscription !== null ? t('task.subscription.unsubscribe') : t('task.subscription.subscribe'))
|
||||||
|
const icon = computed(() => props.subscription !== null ? ['far', 'bell-slash'] : 'bell')
|
||||||
|
const disabled = computed(() => {
|
||||||
|
if (props.subscription === null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.subscription.entity !== props.entity
|
||||||
|
})
|
||||||
|
|
||||||
|
function changeSubscription() {
|
||||||
|
if (disabled.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.subscription === null) {
|
||||||
|
subscribe()
|
||||||
|
} else {
|
||||||
|
unsubscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function subscribe() {
|
||||||
|
const subscription = new SubscriptionModel({
|
||||||
|
entity: props.entity,
|
||||||
|
entityId: props.entityId,
|
||||||
|
})
|
||||||
|
await subscriptionService.value.create(subscription)
|
||||||
|
emit('change', subscription)
|
||||||
|
success({message: t('task.subscription.subscribeSuccess', {entity: props.entity})})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function unsubscribe() {
|
||||||
|
const subscription = new SubscriptionModel({
|
||||||
|
entity: props.entity,
|
||||||
|
entityId: props.entityId,
|
||||||
|
})
|
||||||
|
await subscriptionService.value.delete(subscription)
|
||||||
|
emit('change', null)
|
||||||
|
success({message: t('task.subscription.unsubscribeSuccess', {entity: props.entity})})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -11,31 +11,28 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
export default {
|
defineProps({
|
||||||
name: 'user',
|
user: {
|
||||||
props: {
|
required: true,
|
||||||
user: {
|
type: Object,
|
||||||
required: true,
|
|
||||||
type: Object,
|
|
||||||
},
|
|
||||||
showUsername: {
|
|
||||||
required: false,
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
avatarSize: {
|
|
||||||
required: false,
|
|
||||||
type: Number,
|
|
||||||
default: 50,
|
|
||||||
},
|
|
||||||
isInline: {
|
|
||||||
required: false,
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
showUsername: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
avatarSize: {
|
||||||
|
required: false,
|
||||||
|
type: Number,
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
isInline: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -9,32 +9,23 @@
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
|
import {ref, computed} from 'vue'
|
||||||
|
import {useStore} from 'vuex'
|
||||||
import Multiselect from '@/components/input/multiselect.vue'
|
import Multiselect from '@/components/input/multiselect.vue'
|
||||||
|
|
||||||
export default {
|
const emit = defineEmits(['selected'])
|
||||||
name: 'namespace-search',
|
|
||||||
emits: ['selected'],
|
const query = ref('')
|
||||||
data() {
|
|
||||||
return {
|
const store = useStore()
|
||||||
query: '',
|
const namespaces = computed(() => store.getters['namespaces/searchNamespace'](query.value))
|
||||||
}
|
|
||||||
},
|
function findNamespaces(newQuery: string) {
|
||||||
components: {
|
query.value = newQuery
|
||||||
Multiselect,
|
}
|
||||||
},
|
|
||||||
computed: {
|
function select(namespace) {
|
||||||
namespaces() {
|
emit('selected', namespace)
|
||||||
return this.$store.getters['namespaces/searchNamespace'](this.query)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
findNamespaces(query) {
|
|
||||||
this.query = query
|
|
||||||
},
|
|
||||||
select(namespace) {
|
|
||||||
this.$emit('selected', namespace)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -52,30 +52,22 @@
|
||||||
</dropdown>
|
</dropdown>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import {ref, onMounted} from 'vue'
|
||||||
|
|
||||||
import Dropdown from '@/components/misc/dropdown.vue'
|
import Dropdown from '@/components/misc/dropdown.vue'
|
||||||
import DropdownItem from '@/components/misc/dropdown-item.vue'
|
import DropdownItem from '@/components/misc/dropdown-item.vue'
|
||||||
import TaskSubscription from '@/components/misc/subscription.vue'
|
import TaskSubscription from '@/components/misc/subscription.vue'
|
||||||
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: 'namespace-settings-dropdown',
|
namespace: {
|
||||||
data() {
|
type: Object, // NamespaceModel
|
||||||
return {
|
required: true,
|
||||||
subscription: null,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
components: {
|
})
|
||||||
DropdownItem,
|
|
||||||
Dropdown,
|
const subscription = ref(null)
|
||||||
TaskSubscription,
|
onMounted(() => {
|
||||||
},
|
subscription.value = props.namespace.subscription
|
||||||
props: {
|
})
|
||||||
namespace: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.subscription = this.namespace.subscription
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue