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}"
|
||||
@click.stop="toggleFavoriteList(list)"
|
||||
class="favorite">
|
||||
<icon icon="star" v-if="list.isFavorite"/>
|
||||
<icon :icon="['far', 'star']" v-else/>
|
||||
<icon :icon="list.isFavorite ? 'star' : ['far', 'star']" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="title">{{ list.title }}</div>
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
import {ref, watch} from 'vue'
|
||||
import {useStore} from 'vuex'
|
||||
|
||||
import ListService from '@/services/list'
|
||||
|
||||
export default {
|
||||
name: 'list-card',
|
||||
data() {
|
||||
return {
|
||||
background: null,
|
||||
backgroundLoading: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
const background = ref(null)
|
||||
const backgroundLoading = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Object,
|
||||
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) {
|
||||
})
|
||||
|
||||
watch(props.list, loadBackground, { immediate: true })
|
||||
|
||||
async function loadBackground() {
|
||||
if (props.list === null || !props.list.backgroundInformation || backgroundLoading.value) {
|
||||
return
|
||||
}
|
||||
|
||||
this.backgroundLoading = true
|
||||
backgroundLoading.value = true
|
||||
|
||||
const listService = new ListService()
|
||||
try {
|
||||
this.background = await listService.background(this.list)
|
||||
background.value = await listService.background(props.list)
|
||||
} finally {
|
||||
this.backgroundLoading = false
|
||||
backgroundLoading.value = false
|
||||
}
|
||||
},
|
||||
toggleFavoriteList(list) {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
this.$store.dispatch('lists/toggleListFavorite', list)
|
||||
},
|
||||
},
|
||||
store.dispatch('lists/toggleListFavorite', list)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,39 +2,26 @@
|
|||
<div
|
||||
v-if="isDone"
|
||||
class="is-done"
|
||||
:class="{ 'is-done--small': variant === variants.SMALL }"
|
||||
:class="{ 'is-done--small': variant === 'small' }"
|
||||
>
|
||||
{{ $t('task.attributes.done') }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const VARIANTS = {
|
||||
DEFAULT: 'default',
|
||||
SMALL: 'small',
|
||||
}
|
||||
<script lang="ts" setup>
|
||||
import {PropType} from 'vue'
|
||||
type Variants = 'default' | 'small'
|
||||
|
||||
export default {
|
||||
name: 'Done',
|
||||
|
||||
data() {
|
||||
return {
|
||||
variants: VARIANTS,
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
defineProps({
|
||||
isDone: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default: VARIANTS.DEFAULT,
|
||||
validator: (variant) => Object.values(VARIANTS).includes(variant),
|
||||
type: String as PropType<Variants>,
|
||||
default: 'default',
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
|
|
|
@ -24,10 +24,8 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'card',
|
||||
props: {
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
|
@ -56,9 +54,9 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['close'],
|
||||
}
|
||||
})
|
||||
|
||||
defineEmits(['close'])
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -11,10 +11,8 @@
|
|||
</router-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'dropdown-item',
|
||||
props: {
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
to: {
|
||||
required: true,
|
||||
},
|
||||
|
@ -23,6 +21,5 @@ export default {
|
|||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -7,16 +7,10 @@
|
|||
</message>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Message from '@/components/misc/message'
|
||||
<script lang="ts" setup>
|
||||
import Message from '@/components/misc/message.vue'
|
||||
|
||||
export default {
|
||||
name: 'error',
|
||||
components: {Message},
|
||||
methods: {
|
||||
reload() {
|
||||
function reload() {
|
||||
window.location.reload()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -6,16 +6,14 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
<script lang="ts" setup>
|
||||
import {computed} from 'vue'
|
||||
import {useStore} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'legal',
|
||||
computed: mapState({
|
||||
imprintUrl: state => state.config.legal.imprintUrl,
|
||||
privacyPolicyUrl: state => state.config.legal.privacyPolicyUrl,
|
||||
}),
|
||||
}
|
||||
const store = useStore()
|
||||
|
||||
const imprintUrl = computed(() => store.state.config.legal.imprintUrl)
|
||||
const privacyPolicyUrl = computed(() => store.state.config.legal.privacyPolicyUrl)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -2,12 +2,6 @@
|
|||
<div class="loader-container is-loading"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.loader-container {
|
||||
height: 100%;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
variant: {
|
||||
type: String,
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
<div class="no-auth-wrapper">
|
||||
<div class="noauth-container">
|
||||
<Logo class="logo" width="400" height="117" />
|
||||
<message v-if="motd !== ''" class="my-2">
|
||||
<Message v-if="motd !== ''" class="my-2">
|
||||
{{ motd }}
|
||||
</message>
|
||||
</Message>
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script lang="ts" setup>
|
||||
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 {computed} from 'vue'
|
||||
|
||||
|
|
|
@ -34,8 +34,10 @@
|
|||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
function createPagination(totalPages, currentPage) {
|
||||
<script lang="ts" setup>
|
||||
import {computed} from 'vue'
|
||||
|
||||
function createPagination(totalPages: number, currentPage: number) {
|
||||
const pages = []
|
||||
for (let i = 0; i < totalPages; i++) {
|
||||
|
||||
|
@ -79,10 +81,7 @@ function getRouteForPagination(page = 1, type = 'list') {
|
|||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'Pagination',
|
||||
|
||||
props: {
|
||||
const props = defineProps({
|
||||
totalPages: {
|
||||
type: Number,
|
||||
required: true,
|
||||
|
@ -91,18 +90,9 @@ export default {
|
|||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
computed: {
|
||||
pages() {
|
||||
return createPagination(this.totalPages, this.currentPage)
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getRouteForPagination,
|
||||
},
|
||||
}
|
||||
const pages = computed(() => createPagination(props.totalPages, props.currentPage))
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<section v-else-if="error !== ''">
|
||||
<no-auth-wrapper>
|
||||
<card>
|
||||
<p v-if="error === errorNoApiUrl">
|
||||
<p v-if="error === ERROR_NO_API_URL">
|
||||
{{ $t('ready.noApiUrlConfigured') }}
|
||||
</p>
|
||||
<message variant="danger" v-else>
|
||||
|
@ -40,51 +40,34 @@
|
|||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
import {ref, computed} from 'vue'
|
||||
import {useStore} from 'vuex'
|
||||
|
||||
import Logo from '@/assets/logo.svg?component'
|
||||
import ApiConfig from '@/components/misc/api-config'
|
||||
import Message from '@/components/misc/message'
|
||||
import NoAuthWrapper from '@/components/misc/no-auth-wrapper'
|
||||
import {mapState} from 'vuex'
|
||||
import ApiConfig from '@/components/misc/api-config.vue'
|
||||
import Message from '@/components/misc/message.vue'
|
||||
import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue'
|
||||
|
||||
import {ERROR_NO_API_URL} from '@/helpers/checkAndSetApiUrl'
|
||||
|
||||
export default {
|
||||
name: 'ready',
|
||||
components: {
|
||||
Message,
|
||||
Logo,
|
||||
NoAuthWrapper,
|
||||
ApiConfig,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
error: '',
|
||||
errorNoApiUrl: ERROR_NO_API_URL,
|
||||
const store = useStore()
|
||||
|
||||
const ready = computed(() => store.state.vikunjaReady)
|
||||
const online = computed(() => store.state.online)
|
||||
|
||||
const error = ref('')
|
||||
const showLoading = computed(() => !ready.value && error.value === '')
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
await store.dispatch('loadApp')
|
||||
} 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>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -7,10 +7,8 @@
|
|||
</component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'shortcut',
|
||||
props: {
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
keys: {
|
||||
type: Array,
|
||||
required: true,
|
||||
|
@ -23,8 +21,7 @@ export default {
|
|||
type: String,
|
||||
default: 'div',
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -22,18 +22,16 @@
|
|||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
import {computed, shallowRef} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
import SubscriptionService from '@/services/subscription'
|
||||
import SubscriptionModel from '@/models/subscription'
|
||||
|
||||
export default {
|
||||
name: 'task-subscription',
|
||||
data() {
|
||||
return {
|
||||
subscriptionService: new SubscriptionService(),
|
||||
}
|
||||
},
|
||||
props: {
|
||||
import {success} from '@/message'
|
||||
|
||||
const props = defineProps({
|
||||
entity: {
|
||||
required: true,
|
||||
type: String,
|
||||
|
@ -48,65 +46,65 @@ export default {
|
|||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ['change'],
|
||||
computed: {
|
||||
tooltipText() {
|
||||
if (this.disabled) {
|
||||
return this.$t('task.subscription.subscribedThroughParent', {
|
||||
entity: this.entity,
|
||||
parent: this.subscription.entity,
|
||||
})
|
||||
|
||||
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 this.subscription !== null ?
|
||||
this.$t('task.subscription.subscribed', {entity: this.entity}) :
|
||||
this.$t('task.subscription.notSubscribed', {entity: this.entity})
|
||||
},
|
||||
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 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 this.subscription.entity !== this.entity
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeSubscription() {
|
||||
if (this.disabled) {
|
||||
return props.subscription.entity !== props.entity
|
||||
})
|
||||
|
||||
function changeSubscription() {
|
||||
if (disabled.value) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.subscription === null) {
|
||||
this.subscribe()
|
||||
if (props.subscription === null) {
|
||||
subscribe()
|
||||
} else {
|
||||
this.unsubscribe()
|
||||
unsubscribe()
|
||||
}
|
||||
},
|
||||
async subscribe() {
|
||||
}
|
||||
|
||||
async function subscribe() {
|
||||
const subscription = new SubscriptionModel({
|
||||
entity: this.entity,
|
||||
entityId: this.entityId,
|
||||
entity: props.entity,
|
||||
entityId: props.entityId,
|
||||
})
|
||||
await this.subscriptionService.create(subscription)
|
||||
this.$emit('change', subscription)
|
||||
this.$message.success({message: this.$t('task.subscription.subscribeSuccess', {entity: this.entity})})
|
||||
},
|
||||
async unsubscribe() {
|
||||
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: this.entity,
|
||||
entityId: this.entityId,
|
||||
entity: props.entity,
|
||||
entityId: props.entityId,
|
||||
})
|
||||
await this.subscriptionService.delete(subscription)
|
||||
this.$emit('change', null)
|
||||
this.$message.success({message: this.$t('task.subscription.unsubscribeSuccess', {entity: this.entity})})
|
||||
},
|
||||
},
|
||||
await subscriptionService.value.delete(subscription)
|
||||
emit('change', null)
|
||||
success({message: t('task.subscription.unsubscribeSuccess', {entity: props.entity})})
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -11,10 +11,8 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'user',
|
||||
props: {
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
user: {
|
||||
required: true,
|
||||
type: Object,
|
||||
|
@ -34,8 +32,7 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -9,32 +9,23 @@
|
|||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
import {ref, computed} from 'vue'
|
||||
import {useStore} from 'vuex'
|
||||
import Multiselect from '@/components/input/multiselect.vue'
|
||||
|
||||
export default {
|
||||
name: 'namespace-search',
|
||||
emits: ['selected'],
|
||||
data() {
|
||||
return {
|
||||
query: '',
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Multiselect,
|
||||
},
|
||||
computed: {
|
||||
namespaces() {
|
||||
return this.$store.getters['namespaces/searchNamespace'](this.query)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
findNamespaces(query) {
|
||||
this.query = query
|
||||
},
|
||||
select(namespace) {
|
||||
this.$emit('selected', namespace)
|
||||
},
|
||||
},
|
||||
const emit = defineEmits(['selected'])
|
||||
|
||||
const query = ref('')
|
||||
|
||||
const store = useStore()
|
||||
const namespaces = computed(() => store.getters['namespaces/searchNamespace'](query.value))
|
||||
|
||||
function findNamespaces(newQuery: string) {
|
||||
query.value = newQuery
|
||||
}
|
||||
|
||||
function select(namespace) {
|
||||
emit('selected', namespace)
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -52,30 +52,22 @@
|
|||
</dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import {ref, onMounted} from 'vue'
|
||||
|
||||
import Dropdown from '@/components/misc/dropdown.vue'
|
||||
import DropdownItem from '@/components/misc/dropdown-item.vue'
|
||||
import TaskSubscription from '@/components/misc/subscription.vue'
|
||||
|
||||
export default {
|
||||
name: 'namespace-settings-dropdown',
|
||||
data() {
|
||||
return {
|
||||
subscription: null,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DropdownItem,
|
||||
Dropdown,
|
||||
TaskSubscription,
|
||||
},
|
||||
props: {
|
||||
const props = defineProps({
|
||||
namespace: {
|
||||
type: Object, // NamespaceModel
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.subscription = this.namespace.subscription
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
const subscription = ref(null)
|
||||
onMounted(() => {
|
||||
subscription.value = props.namespace.subscription
|
||||
})
|
||||
</script>
|
||||
|
|
Loading…
Reference in a new issue