feat: convert simple components to script setup and use typescript (#1120)
All checks were successful
continuous-integration/drone/push Build is passing

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #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:
Dominik Pschenitschni 2021-12-04 14:47:32 +00:00 committed by konrad
parent f758eefa88
commit ac630ac775
16 changed files with 298 additions and 387 deletions

View File

@ -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 { const props = defineProps({
background: null,
backgroundLoading: false,
}
},
props: {
list: { list: {
type: Object,
required: true, required: true,
}, },
showArchived: { showArchived: {
default: false, default: false,
type: Boolean, type: Boolean,
}, },
}, })
watch: {
list: { watch(props.list, loadBackground, { immediate: true })
handler: 'loadBackground',
immediate: true, async function loadBackground() {
}, if (props.list === null || !props.list.backgroundInformation || backgroundLoading.value) {
},
methods: {
async loadBackground() {
if (this.list === null || !this.list.backgroundInformation || this.backgroundLoading) {
return return
} }
this.backgroundLoading = true backgroundLoading.value = true
const listService = new ListService() const listService = new ListService()
try { try {
this.background = await listService.background(this.list) background.value = await listService.background(props.list)
} finally { } finally {
this.backgroundLoading = false backgroundLoading.value = false
} }
}, }
toggleFavoriteList(list) {
const store = useStore()
function toggleFavoriteList(list) {
// The favorites pseudo list is always favorite // The favorites pseudo list is always favorite
// Archived lists cannot be marked favorite // Archived lists cannot be marked favorite
if (list.id === -1 || list.isArchived) { if (list.id === -1 || list.isArchived) {
return return
} }
this.$store.dispatch('lists/toggleListFavorite', list) store.dispatch('lists/toggleListFavorite', list)
},
},
} }
</script> </script>

View File

@ -2,39 +2,26 @@
<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',
data() {
return {
variants: VARIANTS,
}
},
props: {
isDone: { isDone: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
variant: { variant: {
type: String, type: String as PropType<Variants>,
default: VARIANTS.DEFAULT, default: 'default',
validator: (variant) => Object.values(VARIANTS).includes(variant),
}, },
}, })
}
</script> </script>

View File

@ -24,10 +24,8 @@
</div> </div>
</template> </template>
<script> <script setup lang="ts">
export default { defineProps({
name: 'card',
props: {
title: { title: {
type: String, type: String,
default: '', default: '',
@ -56,9 +54,9 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}, })
emits: ['close'],
} defineEmits(['close'])
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -11,10 +11,8 @@
</router-link> </router-link>
</template> </template>
<script> <script lang="ts" setup>
export default { defineProps({
name: 'dropdown-item',
props: {
to: { to: {
required: true, required: true,
}, },
@ -23,6 +21,5 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
}, })
}
</script> </script>

View File

@ -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',
components: {Message},
methods: {
reload() {
window.location.reload() window.location.reload()
},
},
} }
</script> </script>

View File

@ -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>

View File

@ -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%;

View File

@ -4,7 +4,7 @@
</div> </div>
</template> </template>
<script setup> <script lang="ts" setup>
defineProps({ defineProps({
variant: { variant: {
type: String, type: String,

View File

@ -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'

View File

@ -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,10 +81,7 @@ function getRouteForPagination(page = 1, type = 'list') {
} }
} }
export default { const props = defineProps({
name: 'Pagination',
props: {
totalPages: { totalPages: {
type: Number, type: Number,
required: true, required: true,
@ -91,18 +90,9 @@ export default {
type: Number, type: Number,
default: 0, default: 0,
}, },
}, })
computed: { const pages = computed(() => createPagination(props.totalPages, props.currentPage))
pages() {
return createPagination(this.totalPages, this.currentPage)
},
},
methods: {
getRouteForPagination,
},
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -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>

View File

@ -7,10 +7,8 @@
</component> </component>
</template> </template>
<script> <script lang="ts" setup>
export default { defineProps({
name: 'shortcut',
props: {
keys: { keys: {
type: Array, type: Array,
required: true, required: true,
@ -23,8 +21,7 @@ export default {
type: String, type: String,
default: 'div', default: 'div',
}, },
}, })
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -22,18 +22,16 @@
</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() { const props = defineProps({
return {
subscriptionService: new SubscriptionService(),
}
},
props: {
entity: { entity: {
required: true, required: true,
type: String, type: String,
@ -48,65 +46,65 @@ export default {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
}, })
emits: ['change'],
computed: { const emit = defineEmits(['change'])
tooltipText() {
if (this.disabled) { const subscriptionService = shallowRef(new SubscriptionService())
return this.$t('task.subscription.subscribedThroughParent', {
entity: this.entity, const {t} = useI18n()
parent: this.subscription.entity, const tooltipText = computed(() => {
if (disabled.value) {
return t('task.subscription.subscribedThroughParent', {
entity: props.entity,
parent: props.subscription.entity,
}) })
} }
return this.subscription !== null ? return props.subscription !== null ?
this.$t('task.subscription.subscribed', {entity: this.entity}) : t('task.subscription.subscribed', {entity: props.entity}) :
this.$t('task.subscription.notSubscribed', {entity: this.entity}) t('task.subscription.notSubscribed', {entity: props.entity})
}, })
buttonText() {
return this.subscription !== null ? this.$t('task.subscription.unsubscribe') : this.$t('task.subscription.subscribe') const buttonText = computed(() => props.subscription !== null ? t('task.subscription.unsubscribe') : t('task.subscription.subscribe'))
}, const icon = computed(() => props.subscription !== null ? ['far', 'bell-slash'] : 'bell')
icon() { const disabled = computed(() => {
return this.subscription !== null ? ['far', 'bell-slash'] : 'bell' if (props.subscription === null) {
},
disabled() {
if (this.subscription === null) {
return false return false
} }
return this.subscription.entity !== this.entity return props.subscription.entity !== props.entity
}, })
},
methods: { function changeSubscription() {
changeSubscription() { if (disabled.value) {
if (this.disabled) {
return return
} }
if (this.subscription === null) { if (props.subscription === null) {
this.subscribe() subscribe()
} else { } else {
this.unsubscribe() unsubscribe()
} }
}, }
async subscribe() {
async function subscribe() {
const subscription = new SubscriptionModel({ const subscription = new SubscriptionModel({
entity: this.entity, entity: props.entity,
entityId: this.entityId, entityId: props.entityId,
}) })
await this.subscriptionService.create(subscription) await subscriptionService.value.create(subscription)
this.$emit('change', subscription) emit('change', subscription)
this.$message.success({message: this.$t('task.subscription.subscribeSuccess', {entity: this.entity})}) success({message: t('task.subscription.subscribeSuccess', {entity: props.entity})})
}, }
async unsubscribe() {
async function unsubscribe() {
const subscription = new SubscriptionModel({ const subscription = new SubscriptionModel({
entity: this.entity, entity: props.entity,
entityId: this.entityId, entityId: props.entityId,
}) })
await this.subscriptionService.delete(subscription) await subscriptionService.value.delete(subscription)
this.$emit('change', null) emit('change', null)
this.$message.success({message: this.$t('task.subscription.unsubscribeSuccess', {entity: this.entity})}) success({message: t('task.subscription.unsubscribeSuccess', {entity: props.entity})})
},
},
} }
</script> </script>

View File

@ -11,10 +11,8 @@
</div> </div>
</template> </template>
<script> <script lang="ts" setup>
export default { defineProps({
name: 'user',
props: {
user: { user: {
required: true, required: true,
type: Object, type: Object,
@ -34,8 +32,7 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}, })
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -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>

View File

@ -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',
data() {
return {
subscription: null,
}
},
components: {
DropdownItem,
Dropdown,
TaskSubscription,
},
props: {
namespace: { namespace: {
type: Object, // NamespaceModel
required: true, required: true,
}, },
}, })
mounted() {
this.subscription = this.namespace.subscription const subscription = ref(null)
}, onMounted(() => {
} subscription.value = props.namespace.subscription
})
</script> </script>