Resolve some TODOs
This commit is contained in:
parent
74d1a0a03e
commit
e7da8b5f43
|
@ -56,7 +56,6 @@ onMounted(async () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Time ago
|
// Time ago
|
||||||
// TODO (wvffle): Migrate to useTimeAgo
|
|
||||||
useIntervalFn(() => {
|
useIntervalFn(() => {
|
||||||
// used to redraw ago dates every minute
|
// used to redraw ago dates every minute
|
||||||
store.commit('ui/computeLastDate')
|
store.commit('ui/computeLastDate')
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { QueueItemSource } from '~/types'
|
import type { QueueItemSource } from '~/types'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'play', index: number): void
|
||||||
|
(e: 'remove', index: number): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
source: QueueItemSource
|
source: QueueItemSource
|
||||||
index: number
|
index: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Emits {
|
defineEmits<Events>()
|
||||||
(e: 'play', index: number): void
|
|
||||||
(e: 'remove', index: number): void
|
|
||||||
}
|
|
||||||
|
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
defineEmits<Emits>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -9,6 +9,10 @@ import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
type Type = 'rss' | 'artists' | 'both'
|
type Type = 'rss' | 'artists' | 'both'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'subscribed', rss: object): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
initialId?: string
|
initialId?: string
|
||||||
initialType?: Type
|
initialType?: Type
|
||||||
|
@ -17,6 +21,7 @@ interface Props {
|
||||||
standalone?: boolean
|
standalone?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
initialId: '',
|
initialId: '',
|
||||||
initialType: 'artists',
|
initialType: 'artists',
|
||||||
|
@ -118,7 +123,6 @@ const createFetch = async () => {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['subscribed'])
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const rssSubscribe = async () => {
|
const rssSubscribe = async () => {
|
||||||
|
|
|
@ -9,13 +9,17 @@ import axios from 'axios'
|
||||||
|
|
||||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:show', show: boolean): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
show: boolean
|
show: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const emit = defineEmits(['update:show'])
|
|
||||||
const show = useVModel(props, 'show', emit)
|
const show = useVModel(props, 'show', emit)
|
||||||
|
|
||||||
const instanceUrl = ref('')
|
const instanceUrl = ref('')
|
||||||
|
|
|
@ -4,12 +4,17 @@ import { useVModel } from '@vueuse/core'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:show', show: boolean): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
show: boolean
|
show: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const emit = defineEmits(['update:show'])
|
|
||||||
const showRef = useVModel(props, 'show', emit)
|
const showRef = useVModel(props, 'show', emit)
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
|
@ -7,16 +7,20 @@ import { computed, ref } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
import { arrayMove } from '~/utils'
|
import { arrayMove } from '~/utils'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:modelValue', value: Form): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: Form
|
modelValue: Form
|
||||||
signupApprovalEnabled?: boolean
|
signupApprovalEnabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
signupApprovalEnabled: false
|
signupApprovalEnabled: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
|
||||||
const value = useVModel(props, 'modelValue', emit, { deep: true })
|
const value = useVModel(props, 'modelValue', emit, { deep: true })
|
||||||
|
|
||||||
const maxFields = ref(10)
|
const maxFields = ref(10)
|
||||||
|
@ -140,7 +144,6 @@ const move = (idx: number, increment: number) => {
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<!-- TODO (wvffle): Add random _id as :key -->
|
|
||||||
<tr
|
<tr
|
||||||
v-for="(field, idx) in value.fields"
|
v-for="(field, idx) in value.fields"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Channel } from '~/types'
|
import type { Channel } from '~/types'
|
||||||
|
|
||||||
import PlayButton from '~/components/audio/PlayButton.vue'
|
|
||||||
import TagsList from '~/components/tags/List.vue'
|
|
||||||
import { momentFormat } from '~/utils/filters'
|
import { momentFormat } from '~/utils/filters'
|
||||||
|
import { useGettext } from 'vue3-gettext'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
|
import PlayButton from '~/components/audio/PlayButton.vue'
|
||||||
|
import TagsList from '~/components/tags/List.vue'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
// TODO (wvffle) : Find type
|
|
||||||
object: Channel
|
object: Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ const updatedAgo = computed(() => moment(props.object.artist?.modification_date)
|
||||||
<div class="card app-card">
|
<div class="card app-card">
|
||||||
<div
|
<div
|
||||||
v-lazy:background-image="imageUrl"
|
v-lazy:background-image="imageUrl"
|
||||||
:class="['ui', 'head-image', {'circular': object.artist.content_category != 'podcast'}, {'padded': object.artist.content_category === 'podcast'}, 'image', {'default-cover': !object.artist.cover}]"
|
:class="['ui', 'head-image', {'circular': object.artist?.content_category != 'podcast'}, {'padded': object.artist?.content_category === 'podcast'}, 'image', {'default-cover': !object.artist?.cover}]"
|
||||||
@click="$router.push({name: 'channels.detail', params: {id: urlId}})"
|
@click="$router.push({name: 'channels.detail', params: {id: urlId}})"
|
||||||
>
|
>
|
||||||
<play-button
|
<play-button
|
||||||
|
@ -59,12 +60,12 @@ const updatedAgo = computed(() => moment(props.object.artist?.modification_date)
|
||||||
class="discrete link"
|
class="discrete link"
|
||||||
:to="{name: 'channels.detail', params: {id: urlId}}"
|
:to="{name: 'channels.detail', params: {id: urlId}}"
|
||||||
>
|
>
|
||||||
{{ object.artist.name }}
|
{{ object.artist?.name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</strong>
|
</strong>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<translate
|
<translate
|
||||||
v-if="object.artist.content_category === 'podcast'"
|
v-if="object.artist?.content_category === 'podcast'"
|
||||||
class="meta ellipsis"
|
class="meta ellipsis"
|
||||||
translate-context="Content/Channel/Paragraph"
|
translate-context="Content/Channel/Paragraph"
|
||||||
translate-plural="%{ count } episodes"
|
translate-plural="%{ count } episodes"
|
||||||
|
@ -76,8 +77,8 @@ const updatedAgo = computed(() => moment(props.object.artist?.modification_date)
|
||||||
<translate
|
<translate
|
||||||
v-else
|
v-else
|
||||||
translate-context="*/*/*"
|
translate-context="*/*/*"
|
||||||
:translate-params="{count: object.artist.tracks_count}"
|
:translate-params="{count: object.artist?.tracks_count}"
|
||||||
:translate-n="object.artist.tracks_count"
|
:translate-n="object.artist?.tracks_count"
|
||||||
translate-plural="%{ count } tracks"
|
translate-plural="%{ count } tracks"
|
||||||
>
|
>
|
||||||
%{ count } track
|
%{ count } track
|
||||||
|
@ -87,7 +88,7 @@ const updatedAgo = computed(() => moment(props.object.artist?.modification_date)
|
||||||
:truncate-size="20"
|
:truncate-size="20"
|
||||||
:limit="2"
|
:limit="2"
|
||||||
:show-more="false"
|
:show-more="false"
|
||||||
:tags="object.artist.tags ?? []"
|
:tags="object.artist?.tags ?? []"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,7 +97,7 @@ const updatedAgo = computed(() => moment(props.object.artist?.modification_date)
|
||||||
v-translate="{ updatedAgo }"
|
v-translate="{ updatedAgo }"
|
||||||
:translate-params="{ updatedAgo }"
|
:translate-params="{ updatedAgo }"
|
||||||
class="meta ellipsis"
|
class="meta ellipsis"
|
||||||
:datetime="object.artist.modification_date"
|
:datetime="object.artist?.modification_date"
|
||||||
:title="updatedTitle"
|
:title="updatedTitle"
|
||||||
>
|
>
|
||||||
%{ updatedAgo }
|
%{ updatedAgo }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Cover, Track, BackendError } from '~/types'
|
import type { Cover, Track, BackendResponse, BackendError } from '~/types'
|
||||||
|
|
||||||
import { clone } from 'lodash-es'
|
import { clone } from 'lodash-es'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
@ -8,6 +8,10 @@ import axios from 'axios'
|
||||||
import PodcastTable from '~/components/audio/podcast/Table.vue'
|
import PodcastTable from '~/components/audio/podcast/Table.vue'
|
||||||
import TrackTable from '~/components/audio/track/Table.vue'
|
import TrackTable from '~/components/audio/track/Table.vue'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'fetched', data: BackendResponse<Track[]>): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
filters: object
|
filters: object
|
||||||
limit?: number
|
limit?: number
|
||||||
|
@ -15,7 +19,7 @@ interface Props {
|
||||||
isPodcast: boolean
|
isPodcast: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['fetched'])
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
limit: 10,
|
limit: 10,
|
||||||
defaultCover: null
|
defaultCover: null
|
||||||
|
|
|
@ -8,7 +8,6 @@ import usePlayer from '~/composables/audio/usePlayer'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
// TODO (wvffle): Is it correct type?
|
|
||||||
entry: Track
|
entry: Track
|
||||||
defaultCover: Cover
|
defaultCover: Cover
|
||||||
}
|
}
|
||||||
|
@ -42,7 +41,7 @@ const duration = computed(() => props.entry.uploads.find(upload => upload.durati
|
||||||
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-else-if="entry.artist.content_category === 'podcast' && defaultCover != undefined"
|
v-else-if="entry.artist?.content_category === 'podcast' && defaultCover != undefined"
|
||||||
v-lazy="$store.getters['instance/absoluteUrl'](defaultCover.urls.medium_square_crop)"
|
v-lazy="$store.getters['instance/absoluteUrl'](defaultCover.urls.medium_square_crop)"
|
||||||
class="channel-image image"
|
class="channel-image image"
|
||||||
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Channel, BackendError } from '~/types'
|
import type { ContentCategory, Channel, BackendError, Tag } from '~/types'
|
||||||
|
|
||||||
import { slugify } from 'transliteration'
|
import { slugify } from 'transliteration'
|
||||||
import { reactive, computed, ref, watchEffect, watch } from 'vue'
|
import { reactive, computed, ref, watchEffect, watch } from 'vue'
|
||||||
|
@ -9,12 +9,21 @@ import axios from 'axios'
|
||||||
import AttachmentInput from '~/components/common/AttachmentInput.vue'
|
import AttachmentInput from '~/components/common/AttachmentInput.vue'
|
||||||
import TagsSelector from '~/components/library/TagsSelector.vue'
|
import TagsSelector from '~/components/library/TagsSelector.vue'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'category', contentCategory: ContentCategory): void
|
||||||
|
(e: 'submittable', value: boolean): void
|
||||||
|
(e: 'loading', value: boolean): void
|
||||||
|
(e: 'errored', errors: string[]): void
|
||||||
|
(e: 'created', channel: Channel): void
|
||||||
|
(e: 'updated', channel: Channel): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
object?: Channel | null
|
object?: Channel | null
|
||||||
step: number
|
step: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['category', 'submittable', 'loading', 'errored', 'created', 'updated'])
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
object: null,
|
object: null,
|
||||||
step: 1
|
step: 1
|
||||||
|
@ -25,7 +34,7 @@ const { $pgettext } = useGettext()
|
||||||
const newValues = reactive({
|
const newValues = reactive({
|
||||||
name: props.object?.artist?.name ?? '',
|
name: props.object?.artist?.name ?? '',
|
||||||
username: props.object?.actor.preferred_username ?? '',
|
username: props.object?.actor.preferred_username ?? '',
|
||||||
tags: props.object?.artist?.tags ?? [],
|
tags: props.object?.artist?.tags?.map(name => ({ name } as Tag)) ?? [] as Tag[],
|
||||||
description: props.object?.artist?.description?.text ?? '',
|
description: props.object?.artist?.description?.text ?? '',
|
||||||
cover: props.object?.artist?.cover?.uuid ?? null,
|
cover: props.object?.artist?.cover?.uuid ?? null,
|
||||||
content_category: props.object?.artist?.content_category ?? 'podcast',
|
content_category: props.object?.artist?.content_category ?? 'podcast',
|
||||||
|
@ -76,11 +85,11 @@ const labels = computed(() => ({
|
||||||
usernamePlaceholder: $pgettext('Content/Channel/Form.Field.Placeholder', 'awesomechannelname')
|
usernamePlaceholder: $pgettext('Content/Channel/Form.Field.Placeholder', 'awesomechannelname')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const submittable = computed(() =>
|
const submittable = computed(() => !!(
|
||||||
newValues.content_category === 'podcast'
|
newValues.content_category === 'podcast'
|
||||||
? newValues.name && newValues.username && newValues.metadata.itunes_category && newValues.metadata.language
|
? newValues.name && newValues.username && newValues.metadata.itunes_category && newValues.metadata.language
|
||||||
: newValues.name && newValues.username
|
: newValues.name && newValues.username
|
||||||
)
|
))
|
||||||
|
|
||||||
watch(() => newValues.name, (name) => {
|
watch(() => newValues.name, (name) => {
|
||||||
if (creating.value) {
|
if (creating.value) {
|
||||||
|
@ -130,7 +139,8 @@ const submit = async () => {
|
||||||
: axios.patch(`channels/${props.object?.uuid}`, payload)
|
: axios.patch(`channels/${props.object?.uuid}`, payload)
|
||||||
|
|
||||||
const response = await request()
|
const response = await request()
|
||||||
emit(creating.value ? 'created' : 'updated', response.data)
|
if (creating.value) emit('created', response.data)
|
||||||
|
else emit('updated', response.data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errors.value = (error as BackendError).backendErrors
|
errors.value = (error as BackendError).backendErrors
|
||||||
emit('errored', errors.value)
|
emit('errored', errors.value)
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { BackendError, Channel } from '~/types'
|
import type { BackendError, BackendResponse, Channel } from '~/types'
|
||||||
|
|
||||||
import { clone } from 'lodash-es'
|
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
|
import { clone } from 'lodash-es'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
import ChannelCard from '~/components/audio/ChannelCard.vue'
|
import ChannelCard from '~/components/audio/ChannelCard.vue'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'fetched', channels: BackendResponse<Channel>): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
filters: object
|
filters: object
|
||||||
limit?: number
|
limit?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['fetched'])
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
limit: 5
|
limit: 5
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,10 +4,16 @@ import type { Library } from '~/types'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'unfollowed'): void
|
||||||
|
(e: 'followed'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
library: Library
|
library: Library
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
@ -15,7 +21,6 @@ const follow = computed(() => store.getters['libraries/follow'](props.library.uu
|
||||||
const isPending = computed(() => follow.value && follow.value.approved === null)
|
const isPending = computed(() => follow.value && follow.value.approved === null)
|
||||||
const isApproved = computed(() => follow.value && (follow.value?.approved === true || (isPending.value && props.library.privacy_level === 'everyone')))
|
const isApproved = computed(() => follow.value && (follow.value?.approved === true || (isPending.value && props.library.privacy_level === 'everyone')))
|
||||||
|
|
||||||
const emit = defineEmits(['followed', 'unfollowed'])
|
|
||||||
const toggle = () => {
|
const toggle = () => {
|
||||||
if (isPending.value || isApproved.value) {
|
if (isPending.value || isApproved.value) {
|
||||||
emit('unfollowed')
|
emit('unfollowed')
|
||||||
|
|
|
@ -152,7 +152,6 @@ const openMenu = () => {
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<button
|
<button
|
||||||
class="item basic"
|
class="item basic"
|
||||||
data-ref="enqueue"
|
|
||||||
:disabled="!playable"
|
:disabled="!playable"
|
||||||
:title="labels.addToQueue"
|
:title="labels.addToQueue"
|
||||||
@click.stop.prevent="enqueue"
|
@click.stop.prevent="enqueue"
|
||||||
|
@ -161,7 +160,6 @@ const openMenu = () => {
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="item basic"
|
class="item basic"
|
||||||
data-ref="enqueueNext"
|
|
||||||
:disabled="!playable"
|
:disabled="!playable"
|
||||||
:title="labels.playNext"
|
:title="labels.playNext"
|
||||||
@click.stop.prevent="enqueueNext()"
|
@click.stop.prevent="enqueueNext()"
|
||||||
|
@ -170,7 +168,6 @@ const openMenu = () => {
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="item basic"
|
class="item basic"
|
||||||
data-ref="playNow"
|
|
||||||
:disabled="!playable"
|
:disabled="!playable"
|
||||||
:title="labels.playNow"
|
:title="labels.playNow"
|
||||||
@click.stop.prevent="enqueueNext(true)"
|
@click.stop.prevent="enqueueNext(true)"
|
||||||
|
@ -213,7 +210,6 @@ const openMenu = () => {
|
||||||
<div class="divider" />
|
<div class="divider" />
|
||||||
<button
|
<button
|
||||||
v-if="filterableArtist"
|
v-if="filterableArtist"
|
||||||
data-ref="filterArtist"
|
|
||||||
class="item basic"
|
class="item basic"
|
||||||
:disabled="!filterableArtist"
|
:disabled="!filterableArtist"
|
||||||
:title="labels.hideArtist"
|
:title="labels.hideArtist"
|
||||||
|
@ -226,7 +222,6 @@ const openMenu = () => {
|
||||||
v-for="obj in getReportableObjects({track, album, artist, playlist, account, channel})"
|
v-for="obj in getReportableObjects({track, album, artist, playlist, account, channel})"
|
||||||
:key="obj.target.type + obj.target.id"
|
:key="obj.target.type + obj.target.id"
|
||||||
class="item basic"
|
class="item basic"
|
||||||
:data-ref="`report${obj.target.type}${obj.target.id}`"
|
|
||||||
@click.stop.prevent="report(obj)"
|
@click.stop.prevent="report(obj)"
|
||||||
>
|
>
|
||||||
<i class="share icon" /> {{ obj.label }}
|
<i class="share icon" /> {{ obj.label }}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// TODO (wvffle): Move most of this stufff to usePlayer
|
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
import VolumeControl from './VolumeControl.vue'
|
import VolumeControl from './VolumeControl.vue'
|
||||||
import TrackFavoriteIcon from '~/components/favorites/TrackFavoriteIcon.vue'
|
import TrackFavoriteIcon from '~/components/favorites/TrackFavoriteIcon.vue'
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { useStore } from '~/store'
|
||||||
|
|
||||||
import onKeyboardShortcut from '~/composables/onKeyboardShortcut'
|
import onKeyboardShortcut from '~/composables/onKeyboardShortcut'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'search'): void
|
(e: 'search'): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ interface Result {
|
||||||
routerUrl: RouteLocationNamedRaw
|
routerUrl: RouteLocationNamedRaw
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
const { focused } = useFocus(search)
|
const { focused } = useFocus(search)
|
||||||
|
|
|
@ -11,6 +11,10 @@ import usePlayOptions from '~/composables/audio/usePlayOptions'
|
||||||
import useReport from '~/composables/moderation/useReport'
|
import useReport from '~/composables/moderation/useReport'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:show', value: boolean): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props extends PlayOptionsProps {
|
interface Props extends PlayOptionsProps {
|
||||||
track: Track
|
track: Track
|
||||||
index: number
|
index: number
|
||||||
|
@ -30,6 +34,7 @@ interface Props extends PlayOptionsProps {
|
||||||
account?: Actor | null
|
account?: Actor | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
isArtist: false,
|
isArtist: false,
|
||||||
isAlbum: false
|
isAlbum: false
|
||||||
|
@ -37,7 +42,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const modal = ref()
|
const modal = ref()
|
||||||
|
|
||||||
const emit = defineEmits(['update:show'])
|
|
||||||
const show = useVModel(props, 'show', emit)
|
const show = useVModel(props, 'show', emit)
|
||||||
|
|
||||||
const { report, getReportableObjects } = useReport()
|
const { report, getReportableObjects } = useReport()
|
||||||
|
@ -280,9 +284,7 @@ const labels = computed(() => ({
|
||||||
<div
|
<div
|
||||||
v-for="obj in getReportableObjects({ track, album: track.album, artist: track.artist })"
|
v-for="obj in getReportableObjects({ track, album: track.album, artist: track.artist })"
|
||||||
:key="obj.target.type + obj.target.id"
|
:key="obj.target.type + obj.target.id"
|
||||||
:ref="`report${obj.target.type}${obj.target.id}`"
|
|
||||||
class="row"
|
class="row"
|
||||||
:data-ref="`report${obj.target.type}${obj.target.id}`"
|
|
||||||
@click.stop.prevent="report(obj)"
|
@click.stop.prevent="report(obj)"
|
||||||
>
|
>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
|
|
|
@ -11,6 +11,10 @@ import usePlayOptions from '~/composables/audio/usePlayOptions'
|
||||||
import useReport from '~/composables/moderation/useReport'
|
import useReport from '~/composables/moderation/useReport'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:show', value: boolean): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props extends PlayOptionsProps {
|
interface Props extends PlayOptionsProps {
|
||||||
track: Track
|
track: Track
|
||||||
index: number
|
index: number
|
||||||
|
@ -30,6 +34,7 @@ interface Props extends PlayOptionsProps {
|
||||||
account?: Actor | null
|
account?: Actor | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
isArtist: false,
|
isArtist: false,
|
||||||
isAlbum: false
|
isAlbum: false
|
||||||
|
@ -37,7 +42,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const modal = ref()
|
const modal = ref()
|
||||||
|
|
||||||
const emit = defineEmits(['update:show'])
|
|
||||||
const show = useVModel(props, 'show', emit)
|
const show = useVModel(props, 'show', emit)
|
||||||
|
|
||||||
const { report, getReportableObjects } = useReport()
|
const { report, getReportableObjects } = useReport()
|
||||||
|
@ -225,9 +229,7 @@ const labels = computed(() => ({
|
||||||
<div
|
<div
|
||||||
v-for="obj in getReportableObjects({ track, album: track.album, artist: track.artist })"
|
v-for="obj in getReportableObjects({ track, album: track.album, artist: track.artist })"
|
||||||
:key="obj.target.type + obj.target.id"
|
:key="obj.target.type + obj.target.id"
|
||||||
:ref="`report${obj.target.type}${obj.target.id}`"
|
|
||||||
class="row"
|
class="row"
|
||||||
:data-ref="`report${obj.target.type}${obj.target.id}`"
|
|
||||||
@click.stop.prevent="report(obj)"
|
@click.stop.prevent="report(obj)"
|
||||||
>
|
>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
|
|
|
@ -14,6 +14,11 @@ import TrackRow from '~/components/audio/track/Row.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'fetched'): void
|
||||||
|
(e: 'page-changed', page: number): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tracks?: Track[]
|
tracks?: Track[]
|
||||||
|
|
||||||
|
@ -28,7 +33,6 @@ interface Props {
|
||||||
isAlbum?: boolean
|
isAlbum?: boolean
|
||||||
isPodcast?: boolean
|
isPodcast?: boolean
|
||||||
|
|
||||||
// TODO (wvffle): Find correct type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
nextUrl?: string | null
|
nextUrl?: string | null
|
||||||
|
@ -41,6 +45,7 @@ interface Props {
|
||||||
unique?: boolean
|
unique?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
tracks: () => [],
|
tracks: () => [],
|
||||||
|
|
||||||
|
@ -95,8 +100,6 @@ const labels = computed(() => ({
|
||||||
artist: $pgettext('*/*/*/Noun', 'Artist')
|
artist: $pgettext('*/*/*/Noun', 'Artist')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const emit = defineEmits(['fetched', 'page-changed'])
|
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
|
@ -255,7 +258,7 @@ const updatePage = (page: number) => {
|
||||||
:total="totalTracks"
|
:total="totalTracks"
|
||||||
:current=" tracks.length > 0 ? page : currentPage"
|
:current=" tracks.length > 0 ? page : currentPage"
|
||||||
:paginate-by="paginateBy"
|
:paginate-by="paginateBy"
|
||||||
@page-changed="updatePage"
|
@update:current="updatePage"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -295,7 +298,7 @@ const updatePage = (page: number) => {
|
||||||
:total="totalTracks"
|
:total="totalTracks"
|
||||||
:current="tracks.length > 0 ? page : currentPage"
|
:current="tracks.length > 0 ? page : currentPage"
|
||||||
:compact="true"
|
:compact="true"
|
||||||
@page-changed="updatePage"
|
@update:current="updatePage"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Track, Listening } from '~/types'
|
import type { Track, Listening } from '~/types'
|
||||||
|
|
||||||
// TODO (wvffle): Fix websocket update (#1534)
|
|
||||||
import { ref, reactive, watch } from 'vue'
|
import { ref, reactive, watch } from 'vue'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
import { clone } from 'lodash-es'
|
import { clone } from 'lodash-es'
|
||||||
|
@ -14,7 +13,7 @@ import TagsList from '~/components/tags/List.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'count', count: number): void
|
(e: 'count', count: number): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +27,7 @@ interface Props {
|
||||||
websocketHandlers?: string[]
|
websocketHandlers?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
isActivity: true,
|
isActivity: true,
|
||||||
showCount: false,
|
showCount: false,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { uniq } from 'lodash-es'
|
||||||
|
|
||||||
import useScopes from '~/composables/auth/useScopes'
|
import useScopes from '~/composables/auth/useScopes'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'updated', application: Application): void
|
(e: 'updated', application: Application): void
|
||||||
(e: 'created', application: Application): void
|
(e: 'created', application: Application): void
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ interface Props {
|
||||||
defaults?: Partial<Application>
|
defaults?: Partial<Application>
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
app: null,
|
app: null,
|
||||||
defaults: () => ({})
|
defaults: () => ({})
|
||||||
|
|
|
@ -315,9 +315,9 @@ fetchOwnedApps()
|
||||||
:key="f.id"
|
:key="f.id"
|
||||||
class="field"
|
class="field"
|
||||||
>
|
>
|
||||||
<label :for="f.id">{{ sharedLabels.fields[f.id].label }}</label>
|
<label :for="f.id">{{ sharedLabels.fields[f.id as FieldId].label }}</label>
|
||||||
<p v-if="sharedLabels.fields[f.id].help">
|
<p v-if="sharedLabels.fields[f.id as FieldId].help">
|
||||||
{{ sharedLabels.fields[f.id].help }}
|
{{ sharedLabels.fields[f.id as FieldId].help }}
|
||||||
</p>
|
</p>
|
||||||
<select
|
<select
|
||||||
v-if="f.type === 'dropdown'"
|
v-if="f.type === 'dropdown'"
|
||||||
|
@ -330,7 +330,7 @@ fetchOwnedApps()
|
||||||
:key="key"
|
:key="key"
|
||||||
:value="c"
|
:value="c"
|
||||||
>
|
>
|
||||||
{{ sharedLabels.fields[f.id].choices[c] }}
|
{{ sharedLabels.fields[f.id as FieldId].choices[c] }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<content-form
|
<content-form
|
||||||
|
|
|
@ -4,7 +4,7 @@ import type { BackendError, Channel } from '~/types'
|
||||||
import { computed, watch, ref } from 'vue'
|
import { computed, watch, ref } from 'vue'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'submittable', value: boolean): void
|
(e: 'submittable', value: boolean): void
|
||||||
(e: 'loading', value: boolean): void
|
(e: 'loading', value: boolean): void
|
||||||
(e: 'created'): void
|
(e: 'created'): void
|
||||||
|
@ -14,7 +14,7 @@ interface Props {
|
||||||
channel: Channel
|
channel: Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const title = ref('')
|
const title = ref('')
|
||||||
|
|
|
@ -5,7 +5,7 @@ import axios from 'axios'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
import { reactive, ref, watch } from 'vue'
|
import { reactive, ref, watch } from 'vue'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'update:modelValue', value: string): void
|
(e: 'update:modelValue', value: string): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ interface Props {
|
||||||
channel: Channel | null
|
channel: Channel | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
modelValue: null,
|
modelValue: null,
|
||||||
channel: null
|
channel: null
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { computed, reactive, ref } from 'vue'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'update:modelValue', value: string): void
|
(e: 'update:modelValue', value: string): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ interface Props {
|
||||||
modelValue: string | null
|
modelValue: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
modelValue: null
|
modelValue: null
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { computed } from 'vue'
|
||||||
|
|
||||||
import LoginModal from '~/components/common/LoginModal.vue'
|
import LoginModal from '~/components/common/LoginModal.vue'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'unsubscribed'): void
|
(e: 'unsubscribed'): void
|
||||||
(e: 'subscribed'): void
|
(e: 'subscribed'): void
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ interface Props {
|
||||||
channel: Channel
|
channel: Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
|
@ -18,7 +18,7 @@ import AlbumSelect from '~/components/channels/AlbumSelect.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'status', status: UploadStatus): void
|
(e: 'status', status: UploadStatus): void
|
||||||
(e: 'step', step: 1 | 2 | 3): void
|
(e: 'step', step: 1 | 2 | 3): void
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ interface UploadedFile extends VueUploadItem {
|
||||||
metadata: Record<string, string>
|
metadata: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
channel: null
|
channel: null
|
||||||
})
|
})
|
||||||
|
@ -55,7 +55,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
// TODO (wvffle): Find types in UploadMetadataForm.vue
|
|
||||||
const errors = ref([] as string[])
|
const errors = ref([] as string[])
|
||||||
|
|
||||||
const values = reactive({
|
const values = reactive({
|
||||||
|
|
|
@ -6,8 +6,7 @@ import { ref, computed, watch } from 'vue'
|
||||||
import TagsSelector from '~/components/library/TagsSelector.vue'
|
import TagsSelector from '~/components/library/TagsSelector.vue'
|
||||||
import AttachmentInput from '~/components/common/AttachmentInput.vue'
|
import AttachmentInput from '~/components/common/AttachmentInput.vue'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
// TODO (wvffle): Find correct type
|
|
||||||
(e: 'values', values: Record<string, string>): void
|
(e: 'values', values: Record<string, string>): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +15,12 @@ interface Props {
|
||||||
values?: Record<string, string> | null
|
values?: Record<string, string> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
values: null
|
values: null
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): This is something like a Track, but `cover` is a plain uuid
|
const newValues = ref({ ...(props.values ?? props.upload.import_metadata) } as Record<string, string>)
|
||||||
const newValues = ref({ ...(props.values ?? props.upload.import_metadata) } as any)
|
|
||||||
|
|
||||||
// computed: {
|
// computed: {
|
||||||
// isLoading () {
|
// isLoading () {
|
||||||
|
|
|
@ -16,14 +16,14 @@ interface Action {
|
||||||
filterChackable?: (item: never) => boolean
|
filterChackable?: (item: never) => boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'action-launched', data: any): void
|
(e: 'action-launched', data: any): void
|
||||||
(e: 'refresh'): void
|
(e: 'refresh'): void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
objectsData: { results: [], count: number }
|
objectsData: { results: [], count: number }
|
||||||
actions: [Action]
|
actions: Action[]
|
||||||
actionUrl: string
|
actionUrl: string
|
||||||
idField?: string
|
idField?: string
|
||||||
refreshable?: boolean
|
refreshable?: boolean
|
||||||
|
@ -32,7 +32,7 @@ interface Props {
|
||||||
customObjects?: Record<string, unknown>[]
|
customObjects?: Record<string, unknown>[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
idField: 'id',
|
idField: 'id',
|
||||||
refreshable: false,
|
refreshable: false,
|
||||||
|
|
|
@ -3,10 +3,9 @@ import type { BackendError } from '~/types'
|
||||||
|
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
// TODO (wvffle): Remove this component
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'action-done', data: any): void
|
(e: 'action-done', data: any): void
|
||||||
(e: 'action-error', error: BackendError): void
|
(e: 'action-error', error: BackendError): void
|
||||||
}
|
}
|
||||||
|
@ -16,7 +15,7 @@ interface Props {
|
||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
|
|
|
@ -7,6 +7,11 @@ import { reactive, ref, watch } from 'vue'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
import useFormData from '~/composables/useFormData'
|
import useFormData from '~/composables/useFormData'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:modelValue', value: string | null): void
|
||||||
|
(e: 'delete'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: string | null
|
modelValue: string | null
|
||||||
imageClass?: string
|
imageClass?: string
|
||||||
|
@ -15,6 +20,7 @@ interface Props {
|
||||||
initialValue?: string | undefined
|
initialValue?: string | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
imageClass: '',
|
imageClass: '',
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -22,7 +28,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
initialValue: undefined
|
initialValue: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'delete'])
|
|
||||||
const value = useVModel(props, 'modelValue', emit)
|
const value = useVModel(props, 'modelValue', emit)
|
||||||
|
|
||||||
const attachment = ref()
|
const attachment = ref()
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:modelValue', value: boolean): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: boolean
|
modelValue: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const emit = defineEmits(['update:modelValue'])
|
|
||||||
const value = useVModel(props, 'modelValue', emit)
|
const value = useVModel(props, 'modelValue', emit)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useVModel, watchDebounced, useTextareaAutosize, syncRef } from '@vueuse
|
||||||
import { ref, computed, watchEffect, onMounted, nextTick } from 'vue'
|
import { ref, computed, watchEffect, onMounted, nextTick } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'update:modelValue', value: string): void
|
(e: 'update:modelValue', value: string): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ interface Props {
|
||||||
charLimit?: number
|
charLimit?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
placeholder: undefined,
|
placeholder: undefined,
|
||||||
autofocus: false,
|
autofocus: false,
|
||||||
|
|
|
@ -2,16 +2,17 @@
|
||||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'confirm'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
action?: () => void
|
action?: () => void
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
// TODO (wvffle): Find correct type
|
confirmColor?: 'danger' | 'success'
|
||||||
confirmColor?: 'danger'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (wvffle): MOVE ALL defineEmits ABOVE defineProps
|
const emit = defineEmits<Events>()
|
||||||
const emit = defineEmits()
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
action: () => {},
|
action: () => {},
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
@ -30,7 +31,7 @@ const confirm = () => {
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
:class="[{disabled: disabled}]"
|
:class="[{disabled: disabled}]"
|
||||||
:disabled="disabled || null"
|
:disabled="disabled"
|
||||||
@click.prevent.stop="showModal = true"
|
@click.prevent.stop="showModal = true"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
@ -3,16 +3,21 @@ import { useVModel } from '@vueuse/core'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:modelValue', value: string): void
|
||||||
|
(e: 'search', query: string): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: string
|
modelValue: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
placeholder: ''
|
placeholder: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'search'])
|
|
||||||
const value = useVModel(props, 'modelValue', emit)
|
const value = useVModel(props, 'modelValue', emit)
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { whenever } from '@vueuse/core'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import clip from 'text-clipper'
|
import clip from 'text-clipper'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'updated', data: unknown): void
|
(e: 'updated', data: unknown): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ interface Props {
|
||||||
truncateLength?: number
|
truncateLength?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
content: null,
|
content: null,
|
||||||
fieldName: 'description',
|
fieldName: 'description',
|
||||||
|
|
|
@ -5,11 +5,11 @@ import useThemeList from '~/composables/useThemeList'
|
||||||
import useTheme from '~/composables/useTheme'
|
import useTheme from '~/composables/useTheme'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'show:shortcuts-modal'): void
|
(e: 'show:shortcuts-modal'): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
const themes = useThemeList()
|
const themes = useThemeList()
|
||||||
|
|
|
@ -6,11 +6,17 @@ import { useVModel } from '@vueuse/core'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:show', value: boolean): void
|
||||||
|
(e: 'showLanguageModalEvent'): void
|
||||||
|
(e: 'showThemeModalEvent'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
show: boolean
|
show: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['update:show', 'showThemeModalEvent', 'showLanguageModalEvent'])
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const show = useVModel(props, 'show', emit)
|
const show = useVModel(props, 'show', emit)
|
||||||
|
@ -53,8 +59,8 @@ const labels = computed(() => ({
|
||||||
class="header"
|
class="header"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="$store.state.auth.profile.avatar && $store.state.auth.profile.avatar.urls.medium_square_crop"
|
v-if="$store.state.auth.profile?.avatar && $store.state.auth.profile?.avatar.urls.medium_square_crop"
|
||||||
v-lazy="$store.getters['instance/absoluteUrl']($store.state.auth.profile.avatar.urls.medium_square_crop)"
|
v-lazy="$store.getters['instance/absoluteUrl']($store.state.auth.profile?.avatar.urls.medium_square_crop)"
|
||||||
alt=""
|
alt=""
|
||||||
class="ui centered small circular image"
|
class="ui centered small circular image"
|
||||||
>
|
>
|
||||||
|
@ -80,7 +86,7 @@ const labels = computed(() => ({
|
||||||
<div
|
<div
|
||||||
class="column"
|
class="column"
|
||||||
role="button"
|
role="button"
|
||||||
@click="[$emit('update:show', false), $emit('showLanguageModalEvent')]"
|
@click="[$emit('update:show', false), emit('showLanguageModalEvent')]"
|
||||||
>
|
>
|
||||||
<i class="language icon user-modal list-icon" />
|
<i class="language icon user-modal list-icon" />
|
||||||
<span class="user-modal list-item">{{ labels.language }}:</span>
|
<span class="user-modal list-item">{{ labels.language }}:</span>
|
||||||
|
@ -94,12 +100,12 @@ const labels = computed(() => ({
|
||||||
<div
|
<div
|
||||||
class="column"
|
class="column"
|
||||||
role="button"
|
role="button"
|
||||||
@click="[$emit('update:show', false), $emit('showThemeModalEvent')]"
|
@click="[$emit('update:show', false), emit('showThemeModalEvent')]"
|
||||||
>
|
>
|
||||||
<i class="palette icon user-modal list-icon" />
|
<i class="palette icon user-modal list-icon" />
|
||||||
<span class="user-modal list-item">{{ labels.theme }}:</span>
|
<span class="user-modal list-item">{{ labels.theme }}:</span>
|
||||||
<div class="right floated">
|
<div class="right floated">
|
||||||
<span class="user-modal list-item"> {{ themes.find(x => x.key === theme).name }}</span>
|
<span class="user-modal list-item"> {{ themes.find(x => x.key === theme)?.name }}</span>
|
||||||
<i class="action-hint chevron right icon user-modal" />
|
<i class="action-hint chevron right icon user-modal" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,7 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(+props.defaultPage)
|
const page = ref(+props.defaultPage)
|
||||||
|
|
||||||
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
|
const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
|
||||||
|
|
|
@ -9,7 +9,7 @@ import LibraryCard from '~/views/content/remote/Card.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'loaded', libraries: Library[]): void
|
(e: 'loaded', libraries: Library[]): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ interface Props {
|
||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const nextPage = ref()
|
const nextPage = ref()
|
||||||
|
|
|
@ -4,6 +4,10 @@ import { useGettext } from 'vue3-gettext'
|
||||||
import { useClipboard, useVModel } from '@vueuse/core'
|
import { useClipboard, useVModel } from '@vueuse/core'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:modelValue', value: string): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: string
|
modelValue: string
|
||||||
defaultShow?: boolean
|
defaultShow?: boolean
|
||||||
|
@ -11,12 +15,12 @@ interface Props {
|
||||||
fieldId: string
|
fieldId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
defaultShow: false,
|
defaultShow: false,
|
||||||
copyButton: false
|
copyButton: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
|
||||||
const value = useVModel(props, 'modelValue', emit)
|
const value = useVModel(props, 'modelValue', emit)
|
||||||
|
|
||||||
const showPassword = ref(props.defaultShow)
|
const showPassword = ref(props.defaultShow)
|
||||||
|
|
|
@ -16,10 +16,15 @@ import AlbumDropdown from './AlbumDropdown.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'deleted'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const object = ref<Album | null>(null)
|
const object = ref<Album | null>(null)
|
||||||
|
@ -81,7 +86,6 @@ const fetchData = async () => {
|
||||||
watch(() => props.id, fetchData, { immediate: true })
|
watch(() => props.id, fetchData, { immediate: true })
|
||||||
watch(page, fetchData)
|
watch(page, fetchData)
|
||||||
|
|
||||||
const emit = defineEmits(['deleted'])
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const remove = async () => {
|
const remove = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
|
|
|
@ -6,7 +6,7 @@ import ChannelEntries from '~/components/audio/ChannelEntries.vue'
|
||||||
import TrackTable from '~/components/audio/track/Table.vue'
|
import TrackTable from '~/components/audio/track/Table.vue'
|
||||||
import PlayButton from '~/components/audio/PlayButton.vue'
|
import PlayButton from '~/components/audio/PlayButton.vue'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'page-changed', page: number): void
|
(e: 'page-changed', page: number): void
|
||||||
(e: 'libraries-loaded', libraries: Library[]): void
|
(e: 'libraries-loaded', libraries: Library[]): void
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ interface Props {
|
||||||
totalTracks: number
|
totalTracks: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
|
|
||||||
const getDiscKey = (disc: Track[]) => disc.map(track => track.id).join('|')
|
const getDiscKey = (disc: Track[]) => disc.map(track => track.id).join('|')
|
||||||
|
|
|
@ -9,6 +9,10 @@ import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
import { getDomain } from '~/utils'
|
import { getDomain } from '~/utils'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'remove'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
artist: Artist | null
|
artist: Artist | null
|
||||||
|
@ -19,6 +23,7 @@ interface Props {
|
||||||
isSerie: boolean
|
isSerie: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const { report, getReportableObjects } = useReport()
|
const { report, getReportableObjects } = useReport()
|
||||||
|
|
||||||
|
@ -35,7 +40,6 @@ const isEmbedable = computed(() => (props.isChannel && props.artist?.channel?.ac
|
||||||
const musicbrainzUrl = computed(() => props.object?.mbid ? `https://musicbrainz.org/release/${props.object.mbid}` : null)
|
const musicbrainzUrl = computed(() => props.object?.mbid ? `https://musicbrainz.org/release/${props.object.mbid}` : null)
|
||||||
const discogsUrl = computed(() => `https://discogs.com/search/?type=release&title=${encodeURI(props.object?.title)}&artist=${encodeURI(props.object?.artist.name)}`)
|
const discogsUrl = computed(() => `https://discogs.com/search/?type=release&title=${encodeURI(props.object?.title)}&artist=${encodeURI(props.object?.artist.name)}`)
|
||||||
|
|
||||||
const emit = defineEmits(['remove'])
|
|
||||||
const remove = () => emit('remove')
|
const remove = () => emit('remove')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
scope: 'all'
|
scope: 'all'
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(+props.defaultPage)
|
const page = ref(+props.defaultPage)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -37,7 +37,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
scope: 'all'
|
scope: 'all'
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(+props.defaultPage)
|
const page = ref(+props.defaultPage)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -13,7 +13,7 @@ import axios from 'axios'
|
||||||
import useEditConfigs from '~/composables/moderation/useEditConfigs'
|
import useEditConfigs from '~/composables/moderation/useEditConfigs'
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'approved', isApproved: boolean): void
|
(e: 'approved', isApproved: boolean): void
|
||||||
(e: 'deleted'): void
|
(e: 'deleted'): void
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ interface Props {
|
||||||
currentState?: ReviewState
|
currentState?: ReviewState
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
currentState: () => ({})
|
currentState: () => ({})
|
||||||
})
|
})
|
||||||
|
@ -41,7 +41,6 @@ const canDelete = computed(() => {
|
||||||
if (props.obj.is_applied || props.obj.is_approved) return false
|
if (props.obj.is_applied || props.obj.is_approved) return false
|
||||||
if (!store.state.auth.authenticated) return false
|
if (!store.state.auth.authenticated) return false
|
||||||
|
|
||||||
// TODO (wvffle): Is it better to compare ids? Is full_username unique?
|
|
||||||
return props.obj.created_by.full_username === store.state.auth.fullUsername
|
return props.obj.created_by.full_username === store.state.auth.fullUsername
|
||||||
|| store.state.auth.availablePermissions.library
|
|| store.state.auth.availablePermissions.library
|
||||||
})
|
})
|
||||||
|
|
|
@ -38,7 +38,6 @@ const canEdit = computed(() => {
|
||||||
if (!store.state.auth.authenticated) return false
|
if (!store.state.auth.authenticated) return false
|
||||||
|
|
||||||
const isOwner = props.object.attributed_to
|
const isOwner = props.object.attributed_to
|
||||||
// TODO (wvffle): Is it better to compare ids? Is full_username unique?
|
|
||||||
&& store.state.auth.fullUsername === props.object.attributed_to.full_username
|
&& store.state.auth.fullUsername === props.object.attributed_to.full_username
|
||||||
|
|
||||||
return isOwner || store.state.auth.availablePermissions.library
|
return isOwner || store.state.auth.availablePermissions.library
|
||||||
|
|
|
@ -20,7 +20,7 @@ import useWebSocketHandler from '~/composables/useWebSocketHandler'
|
||||||
import updateQueryString from '~/composables/updateQueryString'
|
import updateQueryString from '~/composables/updateQueryString'
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'uploads-finished', delta: number):void
|
(e: 'uploads-finished', delta: number):void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ interface Props {
|
||||||
defaultImportReference?: string
|
defaultImportReference?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
defaultImportReference: ''
|
defaultImportReference: ''
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,14 +3,19 @@ import type { FileSystem, FSEntry } from '~/types'
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:modelValue', value: string[]): void
|
||||||
|
(e: 'import'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
data: FileSystem
|
data: FileSystem
|
||||||
loading: boolean
|
loading: boolean
|
||||||
modelValue: string[]
|
modelValue: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const emit = defineEmits(['update:modelValue', 'import'])
|
|
||||||
|
|
||||||
const value = useVModel(props, 'modelValue', emit)
|
const value = useVModel(props, 'modelValue', emit)
|
||||||
const handleClick = (entry: FSEntry) => {
|
const handleClick = (entry: FSEntry) => {
|
||||||
|
|
|
@ -10,12 +10,16 @@ interface ErrorEntry {
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:show', value: boolean): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
upload: Upload
|
upload: Upload
|
||||||
show: boolean
|
show: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['update:show'])
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const show = useVModel(props, 'show', emit)
|
const show = useVModel(props, 'show', emit)
|
||||||
|
|
|
@ -40,7 +40,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
scope: 'all'
|
scope: 'all'
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(+props.defaultPage)
|
const page = ref(+props.defaultPage)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -34,7 +34,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
scope: 'all'
|
scope: 'all'
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(+props.defaultPage)
|
const page = ref(+props.defaultPage)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useStore } from '~/store'
|
||||||
|
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'update:modelValue', tags: Tag[]): void
|
(e: 'update:modelValue', tags: Tag[]): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ interface Props {
|
||||||
modelValue: Tag[]
|
modelValue: Tag[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
|
@ -21,11 +21,17 @@ import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useReport from '~/composables/moderation/useReport'
|
import useReport from '~/composables/moderation/useReport'
|
||||||
import useLogger from '~/composables/useLogger'
|
import useLogger from '~/composables/useLogger'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'deleted'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const { report, getReportableObjects } = useReport()
|
const { report, getReportableObjects } = useReport()
|
||||||
|
|
||||||
const track = ref<Track | null>(null)
|
const track = ref<Track | null>(null)
|
||||||
|
@ -107,7 +113,6 @@ const fetchData = async () => {
|
||||||
|
|
||||||
watch(() => props.id, fetchData, { immediate: true })
|
watch(() => props.id, fetchData, { immediate: true })
|
||||||
|
|
||||||
const emit = defineEmits(['deleted'])
|
|
||||||
const remove = async () => {
|
const remove = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// TODO (wvffle): SORT IMPORTS LIKE SO EVERYWHERE
|
// TODO (wvffle): SORT IMPORTS LIKE SO EVERYWHERE
|
||||||
import type { Track } from '~/types'
|
|
||||||
import type { BuilderFilter, FilterConfig } from './Builder.vue'
|
import type { BuilderFilter, FilterConfig } from './Builder.vue'
|
||||||
|
import type { Track } from '~/types'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
|
@ -16,6 +16,14 @@ import TrackTable from '~/components/audio/track/Table.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
|
type Filter = { candidates: { count: number, sample: Track[] } }
|
||||||
|
type ResponseType = { filters: Array<Filter> }
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update-config', index: number, name: string, value: number[]): void
|
||||||
|
(e: 'delete', index: number): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
index: number
|
index: number
|
||||||
|
|
||||||
|
@ -23,10 +31,7 @@ interface Props {
|
||||||
config: FilterConfig
|
config: FilterConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type Filter = { candidates: { count: number, sample: Track[] } }
|
const emit = defineEmits<Events>()
|
||||||
type ResponseType = { filters: Array<Filter> }
|
|
||||||
|
|
||||||
const emit = defineEmits(['update-config', 'delete'])
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
@ -127,7 +132,6 @@ watch(exclude, fetchCandidates)
|
||||||
<div
|
<div
|
||||||
v-for="f in filter.fields"
|
v-for="f in filter.fields"
|
||||||
:key="f.name"
|
:key="f.name"
|
||||||
:ref="f.name"
|
|
||||||
class="ui field"
|
class="ui field"
|
||||||
>
|
>
|
||||||
<div :class="['ui', 'search', 'selection', 'dropdown', {'autocomplete': f.autocomplete}, {'multiple': f.type === 'list'}]">
|
<div :class="['ui', 'search', 'selection', 'dropdown', {'autocomplete': f.autocomplete}, {'multiple': f.type === 'list'}]">
|
||||||
|
|
|
@ -17,7 +17,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -32,7 +31,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
filters: () => ({})
|
filters: () => ({})
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
@ -47,8 +45,6 @@ const orderingOptions: [OrderingField, keyof typeof sharedLabels.filters][] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
const actionFilters = computed(() => ({ q: query.value, ...props.filters }))
|
const actionFilters = computed(() => ({ q: query.value, ...props.filters }))
|
||||||
// TODO (wvffle): Find correct type
|
|
||||||
const actions: unknown[] = []
|
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
@ -176,7 +172,7 @@ const labels = computed(() => ({
|
||||||
<action-table
|
<action-table
|
||||||
v-if="result"
|
v-if="result"
|
||||||
:objects-data="result"
|
:objects-data="result"
|
||||||
:actions="actions"
|
:actions="[]"
|
||||||
action-url="manage/library/artists/action/"
|
action-url="manage/library/artists/action/"
|
||||||
:filters="actionFilters"
|
:filters="actionFilters"
|
||||||
@action-launched="fetchData"
|
@action-launched="fetchData"
|
||||||
|
|
|
@ -17,8 +17,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): Remove from EVERY SINGLE component that does not use it at all
|
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -35,7 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -17,7 +17,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -34,7 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -20,7 +20,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -38,7 +37,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
const configs = useEditConfigs()
|
const configs = useEditConfigs()
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
|
|
||||||
type StateTarget = { id: number, type: keyof typeof targets }
|
type StateTarget = { id: number, type: keyof typeof targets }
|
||||||
|
|
|
@ -17,7 +17,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -34,7 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -19,7 +19,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -36,7 +35,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -17,7 +17,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -34,7 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -20,7 +20,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -37,7 +36,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -17,7 +17,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -34,7 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
const search = ref()
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends OrderingProps {
|
interface Props extends OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
allowListEnabled?: boolean
|
allowListEnabled?: boolean
|
||||||
|
|
||||||
|
@ -29,7 +28,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
allowListEnabled: false
|
allowListEnabled: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'save', data: InstancePolicy): void
|
(e: 'save', data: InstancePolicy): void
|
||||||
(e: 'delete'): void
|
(e: 'delete'): void
|
||||||
(e: 'cancel'): void
|
(e: 'cancel'): void
|
||||||
|
@ -19,7 +19,7 @@ interface Props {
|
||||||
object?: InstancePolicy | null
|
object?: InstancePolicy | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
object: null
|
object: null
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ import axios from 'axios'
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'created', note: Note): void
|
(e: 'created', note: Note): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ interface Props {
|
||||||
target: Note
|
target: Note
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
|
@ -8,13 +8,16 @@ import axios from 'axios'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'deleted', uuid: string): void
|
||||||
|
}
|
||||||
interface Props {
|
interface Props {
|
||||||
notes: Note[]
|
notes: Note[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
|
|
||||||
const emit = defineEmits(['deleted'])
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const remove = async (note: Note) => {
|
const remove = async (note: Note) => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
|
|
|
@ -16,7 +16,7 @@ import useReportConfigs from '~/composables/moderation/useReportConfigs'
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useMarkdown from '~/composables/useMarkdown'
|
import useMarkdown from '~/composables/useMarkdown'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'updated', updating: { type: string }): void
|
(e: 'updated', updating: { type: string }): void
|
||||||
(e: 'handled', isHandled: boolean): void
|
(e: 'handled', isHandled: boolean): void
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ interface Props {
|
||||||
initObj: Report
|
initObj: Report
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const configs = useReportConfigs()
|
const configs = useReportConfigs()
|
||||||
|
|
|
@ -11,7 +11,7 @@ import NoteForm from '~/components/manage/moderation/NoteForm.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'handled', status: UserRequestStatus): void
|
(e: 'handled', status: UserRequestStatus): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ interface Props {
|
||||||
initObj: UserRequest
|
initObj: UserRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
|
@ -17,7 +17,6 @@ import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends OrderingProps {
|
interface Props extends OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -28,7 +27,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
filters: () => ({})
|
filters: () => ({})
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends OrderingProps {
|
interface Props extends OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -27,7 +26,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
filters: () => ({})
|
filters: () => ({})
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
const query = ref('')
|
const query = ref('')
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
|
@ -58,8 +56,6 @@ const permissions = computed(() => [
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
const actionFilters = computed(() => ({ q: query.value, ...props.filters }))
|
const actionFilters = computed(() => ({ q: query.value, ...props.filters }))
|
||||||
// TODO (wvffle): Find correct type
|
|
||||||
const actions: unknown[] = []
|
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
@ -158,7 +154,7 @@ const labels = computed(() => ({
|
||||||
<action-table
|
<action-table
|
||||||
v-if="result"
|
v-if="result"
|
||||||
:objects-data="result"
|
:objects-data="result"
|
||||||
:actions="actions"
|
:actions="[]"
|
||||||
:action-url="'manage/library/uploads/action/'"
|
:action-url="'manage/library/uploads/action/'"
|
||||||
:filters="actionFilters"
|
:filters="actionFilters"
|
||||||
@action-launched="fetchData"
|
@action-launched="fetchData"
|
||||||
|
|
|
@ -4,6 +4,10 @@ import { useGettext } from 'vue3-gettext'
|
||||||
import useSharedLabels from '~/composables/locale/useSharedLabels'
|
import useSharedLabels from '~/composables/locale/useSharedLabels'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:modelValue', value: string): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: string
|
modelValue: string
|
||||||
all?: boolean
|
all?: boolean
|
||||||
|
@ -13,6 +17,7 @@ interface Props {
|
||||||
restrictTo?: string[] // TODO (wvffle): Make sure its string list
|
restrictTo?: string[] // TODO (wvffle): Make sure its string list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
all: false,
|
all: false,
|
||||||
label: false,
|
label: false,
|
||||||
|
@ -21,7 +26,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
restrictTo: () => []
|
restrictTo: () => []
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
|
||||||
const value = useVModel(props, 'modelValue', emit)
|
const value = useVModel(props, 'modelValue', emit)
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
|
@ -94,16 +94,12 @@ const handleAction = (handler?: () => void) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const approveLibraryFollow = async (follow: LibraryFollow) => {
|
const approveLibraryFollow = async (follow: LibraryFollow) => {
|
||||||
follow.isLoading = true
|
|
||||||
await axios.post(`federation/follows/library/${follow.uuid}/accept/`)
|
await axios.post(`federation/follows/library/${follow.uuid}/accept/`)
|
||||||
follow.isLoading = false
|
|
||||||
follow.approved = true
|
follow.approved = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const rejectLibraryFollow = async (follow: LibraryFollow) => {
|
const rejectLibraryFollow = async (follow: LibraryFollow) => {
|
||||||
follow.isLoading = true
|
|
||||||
await axios.post(`federation/follows/library/${follow.uuid}/reject/`)
|
await axios.post(`federation/follows/library/${follow.uuid}/reject/`)
|
||||||
follow.isLoading = false
|
|
||||||
follow.approved = false
|
follow.approved = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,23 +1,31 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Playlist, Track, PlaylistTrack, BackendError, APIErrorResponse } from '~/types'
|
import type { Playlist, Track, PlaylistTrack, BackendError, APIErrorResponse } from '~/types'
|
||||||
|
|
||||||
import { useStore } from '~/store'
|
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
import { computed, ref } from 'vue'
|
|
||||||
import axios from 'axios'
|
|
||||||
import PlaylistForm from '~/components/playlists/Form.vue'
|
|
||||||
import draggable from 'vuedraggable'
|
|
||||||
import { useVModels } from '@vueuse/core'
|
import { useVModels } from '@vueuse/core'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
import PlaylistForm from '~/components/playlists/Form.vue'
|
||||||
|
|
||||||
import useQueue from '~/composables/audio/useQueue'
|
import useQueue from '~/composables/audio/useQueue'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:playlistTracks', value: PlaylistTrack[]): void
|
||||||
|
(e: 'update:playlist', value: Playlist): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
playlist: Playlist | null
|
playlist: Playlist | null
|
||||||
playlistTracks: PlaylistTrack[]
|
playlistTracks: PlaylistTrack[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const emit = defineEmits(['update:playlist', 'update:playlistTracks'])
|
|
||||||
const { playlistTracks, playlist } = useVModels(props, emit)
|
const { playlistTracks, playlist } = useVModels(props, emit)
|
||||||
|
|
||||||
const errors = ref([] as string[])
|
const errors = ref([] as string[])
|
||||||
|
@ -72,8 +80,6 @@ const responseHandlers = {
|
||||||
return this.errored(error)
|
return this.errored(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (wvffle): Test if it works
|
|
||||||
// if (errors.length === 1 && errors[0].code === 'tracks_already_exist_in_playlist') {
|
|
||||||
if (backendErrors.length === 1 && backendErrors[0] === 'Tracks already exist in playlist') {
|
if (backendErrors.length === 1 && backendErrors[0] === 'Tracks already exist in playlist') {
|
||||||
duplicateTrackAddInfo.value = rawPayload ?? null
|
duplicateTrackAddInfo.value = rawPayload ?? null
|
||||||
showDuplicateTrackAddConfirmation.value = true
|
showDuplicateTrackAddConfirmation.value = true
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Playlist, PrivacyLevel, BackendError } from '~/types'
|
import type { Playlist, PrivacyLevel, BackendError } from '~/types'
|
||||||
|
|
||||||
import $ from 'jquery'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { useVModels, useCurrentElement } from '@vueuse/core'
|
import { useVModels, useCurrentElement } from '@vueuse/core'
|
||||||
|
import { ref, computed, onMounted, nextTick } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
import { ref, computed, onMounted, nextTick } from 'vue'
|
|
||||||
import useLogger from '~/composables/useLogger'
|
import axios from 'axios'
|
||||||
|
import $ from 'jquery'
|
||||||
|
|
||||||
import useSharedLabels from '~/composables/locale/useSharedLabels'
|
import useSharedLabels from '~/composables/locale/useSharedLabels'
|
||||||
|
import useLogger from '~/composables/useLogger'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:playlist', value: Playlist): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title?: boolean
|
title?: boolean
|
||||||
|
@ -16,13 +22,13 @@ interface Props {
|
||||||
playlist?: Playlist | null
|
playlist?: Playlist | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
title: true,
|
title: true,
|
||||||
create: false,
|
create: false,
|
||||||
playlist: null
|
playlist: null
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:playlist'])
|
|
||||||
const { playlist } = useVModels(props, emit)
|
const { playlist } = useVModels(props, emit)
|
||||||
|
|
||||||
const logger = useLogger()
|
const logger = useLogger()
|
||||||
|
|
|
@ -5,6 +5,14 @@ import { computed, onBeforeUnmount, ref, watchEffect } from 'vue'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:show', show: boolean): void
|
||||||
|
(e: 'approved'): void
|
||||||
|
(e: 'deny'): void
|
||||||
|
(e: 'show'): void
|
||||||
|
(e: 'hide'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
show: boolean
|
show: boolean
|
||||||
fullscreen?: boolean
|
fullscreen?: boolean
|
||||||
|
@ -12,14 +20,13 @@ interface Props {
|
||||||
additionalClasses?: string[]
|
additionalClasses?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
fullscreen: true,
|
fullscreen: true,
|
||||||
scrolling: false,
|
scrolling: false,
|
||||||
additionalClasses: () => []
|
additionalClasses: () => []
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['approved', 'deny', 'update:show', 'show', 'hide'])
|
|
||||||
|
|
||||||
const modal = ref()
|
const modal = ref()
|
||||||
const { activate, deactivate, pause, unpause } = useFocusTrap(modal, {
|
const { activate, deactivate, pause, unpause } = useFocusTrap(modal, {
|
||||||
allowOutsideClick: true
|
allowOutsideClick: true
|
||||||
|
|
|
@ -4,6 +4,10 @@ import { range, clamp } from 'lodash-es'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'update:current', page: number): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
current?: number
|
current?: number
|
||||||
paginateBy?: number
|
paginateBy?: number
|
||||||
|
@ -11,13 +15,13 @@ interface Props {
|
||||||
compact?: boolean
|
compact?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
current: 1,
|
current: 1,
|
||||||
paginateBy: 25,
|
paginateBy: 25,
|
||||||
compact: false
|
compact: false
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:current', 'pageChanged'])
|
|
||||||
const current = useVModel(props, 'current', emit)
|
const current = useVModel(props, 'current', emit)
|
||||||
|
|
||||||
const RANGE = 2
|
const RANGE = 2
|
||||||
|
@ -47,8 +51,6 @@ const setPage = (page: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
current.value = page
|
current.value = page
|
||||||
// TODO (wvffle): Compat before change to v-model
|
|
||||||
emit('pageChanged', page)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { ref, watchEffect, reactive } from 'vue'
|
||||||
import { RecycleScroller } from 'vue-virtual-scroller'
|
import { RecycleScroller } from 'vue-virtual-scroller'
|
||||||
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'reorder', from: number, to: number): void
|
(e: 'reorder', from: number, to: number): void
|
||||||
(e: 'visible'): void
|
(e: 'visible'): void
|
||||||
(e: 'hidden'): void
|
(e: 'hidden'): void
|
||||||
|
@ -18,7 +18,7 @@ interface Props {
|
||||||
size: number
|
size: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const ghostContainer = ref()
|
const ghostContainer = ref()
|
||||||
|
|
|
@ -23,8 +23,6 @@ export interface PlayOptionsProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (props: PlayOptionsProps) => {
|
export default (props: PlayOptionsProps) => {
|
||||||
// TODO (wvffle): Test if we can defineProps in composable
|
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const { resume, pause, playing } = usePlayer()
|
const { resume, pause, playing } = usePlayer()
|
||||||
const { currentTrack } = useQueue()
|
const { currentTrack } = useQueue()
|
||||||
|
@ -95,7 +93,7 @@ export default (props: PlayOptionsProps) => {
|
||||||
|
|
||||||
const tracks: Track[] = []
|
const tracks: Track[] = []
|
||||||
|
|
||||||
// TODO (wvffle): There is no channel?
|
// TODO (wvffle): Why is there no channel?
|
||||||
if (props.tracks?.length) {
|
if (props.tracks?.length) {
|
||||||
tracks.push(...props.tracks)
|
tracks.push(...props.tracks)
|
||||||
} else if (props.track) {
|
} else if (props.track) {
|
||||||
|
@ -126,7 +124,6 @@ export default (props: PlayOptionsProps) => {
|
||||||
tracks.push(...await getTracksPage({ library: props.library.uuid, ordering: '-creation_date' }))
|
tracks.push(...await getTracksPage({ library: props.library.uuid, ordering: '-creation_date' }))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (wvffle): It was behind 250ms timeout, why?
|
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
|
|
||||||
return tracks.filter(track => track.uploads?.length).map(markRaw)
|
return tracks.filter(track => track.uploads?.length).map(markRaw)
|
||||||
|
|
|
@ -16,7 +16,6 @@ export default (defaultQuery: MaybeRef<string>, updateUrl: MaybeRef<boolean>) =>
|
||||||
const tokens = ref([] as Token[])
|
const tokens = ref([] as Token[])
|
||||||
|
|
||||||
watch(query, (value) => {
|
watch(query, (value) => {
|
||||||
// TODO (wvffle): Move normalizeQuery and parseTokens into the composable file
|
|
||||||
tokens.value = parseTokens(normalizeQuery(value))
|
tokens.value = parseTokens(normalizeQuery(value))
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ import useTheme from '~/composables/useTheme'
|
||||||
// NOTE: Set the theme as fast as possible
|
// NOTE: Set the theme as fast as possible
|
||||||
useTheme()
|
useTheme()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure V_FOR_REF works
|
|
||||||
// Search pattern: v-for([^>]|\n)+?[^h]ref
|
|
||||||
const logger = useLogger()
|
const logger = useLogger()
|
||||||
logger.info('Loading environment:', import.meta.env.MODE)
|
logger.info('Loading environment:', import.meta.env.MODE)
|
||||||
logger.debug('Environment variables:', import.meta.env)
|
logger.debug('Environment variables:', import.meta.env)
|
||||||
|
@ -49,11 +47,4 @@ Promise.all(modules).finally(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Rename filters from useSharedLabels to filters from backend
|
// TODO (wvffle): Rename filters from useSharedLabels to filters from backend
|
||||||
// TODO (wvffle): Check for mixin merging: https://v3-migration.vuejs.org/breaking-changes/data-option.html#mixin-merge-behavior-change=
|
// TODO (wvffle): Migrate EmbedFrame.vue to <script setup lang="ts"> and remove allowJs from tsconfig.json
|
||||||
// TODO (wvffle): Use emits options: https://v3-migration.vuejs.org/breaking-changes/emits-option.html
|
|
||||||
// TODO (wvffle): Find all array watchers and make them deep
|
|
||||||
// TODO (wvffle): Migrate to <script setup lang="ts"> and remove allowJs from tsconfig.json
|
|
||||||
// TODO (wvffle): Replace `from '(../)+` with `from '~/`
|
|
||||||
// TODO (wvffle): Fix props not being available in template in IntelliJ Idea
|
|
||||||
// TODO (wvffle): Use navigation guards
|
|
||||||
// TODO (wvffle): Use computedEager whenever there is a cheap operation that can be executed eagerly
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import type { RouteRecordRaw } from 'vue-router'
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
import { requireLoggedOut, requireLoggedIn } from '../guards'
|
import { requireLoggedOut, requireLoggedIn } from '~/router/guards'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
component: () => import('~/views/auth/Login.vue'),
|
component: () => import('~/views/auth/Login.vue'),
|
||||||
// TODO (wvffle): Use named routes EVERYWHERE
|
|
||||||
props: route => ({ next: route.query.next || '/library' }),
|
props: route => ({ next: route.query.next || '/library' }),
|
||||||
beforeEnter: requireLoggedOut({ name: 'library.index' })
|
beforeEnter: requireLoggedOut({ name: 'library.index' })
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,7 @@ import manage from './manage'
|
||||||
import store from '~/store'
|
import store from '~/store'
|
||||||
import auth from './auth'
|
import auth from './auth'
|
||||||
import user from './user'
|
import user from './user'
|
||||||
import { requireLoggedIn } from '../guards'
|
import { requireLoggedIn } from '~/router/guards'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
|
|
|
@ -246,7 +246,7 @@ export default [
|
||||||
// browse a single library via it's uuid
|
// browse a single library via it's uuid
|
||||||
path: ':id([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})',
|
path: ':id([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})',
|
||||||
props: true,
|
props: true,
|
||||||
component: () => import('~/views/library/DetailBase.vue'),
|
component: () => import('~/views/library/LibraryBase.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
|
|
@ -9,13 +9,13 @@ export interface State {
|
||||||
frontSettings: FrontendSettings
|
frontSettings: FrontendSettings
|
||||||
instanceUrl?: string
|
instanceUrl?: string
|
||||||
knownInstances: string[]
|
knownInstances: string[]
|
||||||
nodeinfo: unknown | null // TODO (wvffle): Get nodeinfo type from swagger automatically
|
nodeinfo: unknown | null
|
||||||
settings: Settings
|
settings: Settings
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FrontendSettings {
|
interface FrontendSettings {
|
||||||
defaultServerUrl: string
|
defaultServerUrl: string
|
||||||
additionalStylesheets: string[] // TODO (wvffle): Ensure it's not nullable
|
additionalStylesheets: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InstanceSettings {
|
interface InstanceSettings {
|
||||||
|
|
|
@ -19,13 +19,11 @@ export interface CurrentRadio {
|
||||||
clientOnly: boolean
|
clientOnly: boolean
|
||||||
session: null
|
session: null
|
||||||
type: 'account'
|
type: 'account'
|
||||||
// TODO (wvffle): Find correct type
|
customRadioId: number
|
||||||
customRadioId: unknown
|
|
||||||
config: RadioConfig
|
config: RadioConfig
|
||||||
objectId: ObjectId | null
|
objectId: ObjectId | null
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (wvffle): Find correct type
|
|
||||||
export type RadioConfig = { type: 'tag', names: string[] } | { type: 'artist', ids: string[] }
|
export type RadioConfig = { type: 'tag', names: string[] } | { type: 'artist', ids: string[] }
|
||||||
|
|
||||||
export interface PopulateQueuePayload {
|
export interface PopulateQueuePayload {
|
||||||
|
|
|
@ -24,7 +24,6 @@ export interface QueueItemSource {
|
||||||
duration: string
|
duration: string
|
||||||
coverUrl: string
|
coverUrl: string
|
||||||
|
|
||||||
// TODO (wvffle): Maybe use <translate> component to avoid passing the labels
|
|
||||||
labels: {
|
labels: {
|
||||||
remove: string
|
remove: string
|
||||||
selectTrack: string
|
selectTrack: string
|
||||||
|
@ -53,6 +52,7 @@ export interface Artist {
|
||||||
description: Content
|
description: Content
|
||||||
cover?: Cover
|
cover?: Cover
|
||||||
channel?: Channel
|
channel?: Channel
|
||||||
|
// TODO (wvffle): Check if it's Tag[] or string[]
|
||||||
tags: string[]
|
tags: string[]
|
||||||
|
|
||||||
content_category: ContentCategory
|
content_category: ContentCategory
|
||||||
|
@ -164,9 +164,6 @@ export interface LibraryFollow {
|
||||||
name: string
|
name: string
|
||||||
type?: 'music.Library' | 'federation.LibraryFollow'
|
type?: 'music.Library' | 'federation.LibraryFollow'
|
||||||
target: Library
|
target: Library
|
||||||
|
|
||||||
// TODO (wvffle): Check if it's not added only on frontend side
|
|
||||||
isLoading?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Cover {
|
export interface Cover {
|
||||||
|
@ -225,6 +222,11 @@ export interface BackendError extends AxiosError {
|
||||||
rawPayload?: APIErrorResponse
|
rawPayload?: APIErrorResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BackendResponse<T> {
|
||||||
|
count: number
|
||||||
|
results: T[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface RateLimitStatus {
|
export interface RateLimitStatus {
|
||||||
limit: string
|
limit: string
|
||||||
scope: string
|
scope: string
|
||||||
|
@ -251,14 +253,14 @@ export interface FileSystem {
|
||||||
|
|
||||||
export interface FSLogs {
|
export interface FSLogs {
|
||||||
status: 'pending' | 'started'
|
status: 'pending' | 'started'
|
||||||
reference: unknown // TODO (wvffle): Find correct type
|
reference: unknown
|
||||||
logs: string[]
|
logs: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content stuff
|
// Content stuff
|
||||||
export interface Content {
|
export interface Content {
|
||||||
content_type: 'text/plain' | 'text/markdown'
|
content_type: 'text/plain' | 'text/markdown'
|
||||||
text: string // TODO (wvffle): Ensure it's not nullable from backend side
|
text: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form stuff
|
// Form stuff
|
||||||
|
@ -311,8 +313,7 @@ export interface User {
|
||||||
id: string
|
id: string
|
||||||
avatar?: Cover
|
avatar?: Cover
|
||||||
email: string
|
email: string
|
||||||
// TODO (wvffle): Is it really a string? Or maybe it's { text: string, content_type: string }
|
summary: { text: string, content_type: string }
|
||||||
summary: string
|
|
||||||
username: string
|
username: string
|
||||||
full_username: string
|
full_username: string
|
||||||
instance_support_message_display_date: string
|
instance_support_message_display_date: string
|
||||||
|
@ -361,7 +362,7 @@ export interface SettingsDataEntry {
|
||||||
export interface Note {
|
export interface Note {
|
||||||
uuid: string
|
uuid: string
|
||||||
type: 'request' | 'report'
|
type: 'request' | 'report'
|
||||||
author?: Actor // TODO (wvffle): Check if is valid
|
author?: Actor
|
||||||
summary?: string
|
summary?: string
|
||||||
creation_date?: string
|
creation_date?: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@ const paginateBy = ref(25)
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
||||||
// TODO (wvffle): Check if can rename to Category
|
|
||||||
interface SearchType {
|
interface SearchType {
|
||||||
id: QueryType
|
id: QueryType
|
||||||
label: string
|
label: string
|
||||||
|
@ -132,7 +131,6 @@ const updateQueryString = () => router.replace({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Debounce all `fetchData` functions
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
if (!query.value) {
|
if (!query.value) {
|
||||||
|
@ -358,10 +356,9 @@ const radioConfig = computed(() => {
|
||||||
|
|
||||||
<pagination
|
<pagination
|
||||||
v-if="currentResults && currentResults.count > paginateBy"
|
v-if="currentResults && currentResults.count > paginateBy"
|
||||||
:current="page"
|
v-model:current="page"
|
||||||
:paginate-by="paginateBy"
|
:paginate-by="paginateBy"
|
||||||
:total="currentResults.count"
|
:total="currentResults.count"
|
||||||
@page-changed="page = $event"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -19,7 +19,6 @@ import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find more types
|
|
||||||
mode?: 'card'
|
mode?: 'card'
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
|
|
@ -18,10 +18,15 @@ import TagsList from '~/components/tags/List.vue'
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useReport from '~/composables/moderation/useReport'
|
import useReport from '~/composables/moderation/useReport'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'deleted'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
const { report, getReportableObjects } = useReport()
|
const { report, getReportableObjects } = useReport()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
@ -100,7 +105,6 @@ watchEffect(() => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['deleted'])
|
|
||||||
const remove = async () => {
|
const remove = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -20,11 +20,13 @@ import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useSmartSearch from '~/composables/useSmartSearch'
|
import useSmartSearch from '~/composables/useSmartSearch'
|
||||||
import useOrdering from '~/composables/useOrdering'
|
import useOrdering from '~/composables/useOrdering'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'fetch-start'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props extends SmartSearchProps, OrderingProps {
|
interface Props extends SmartSearchProps, OrderingProps {
|
||||||
// TODO (wvffle): find object type
|
|
||||||
filters?: object
|
filters?: object
|
||||||
needsRefresh?: boolean
|
needsRefresh?: boolean
|
||||||
// TODO (wvffle): find object type
|
|
||||||
customObjects?: any[]
|
customObjects?: any[]
|
||||||
|
|
||||||
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
// TODO(wvffle): Remove after https://github.com/vuejs/core/pull/4512 is merged
|
||||||
|
@ -33,8 +35,7 @@ interface Props extends SmartSearchProps, OrderingProps {
|
||||||
updateUrl?: boolean
|
updateUrl?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const search = ref()
|
const emit = defineEmits<Events>()
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
defaultQuery: '',
|
defaultQuery: '',
|
||||||
updateUrl: false,
|
updateUrl: false,
|
||||||
|
@ -43,6 +44,8 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
customObjects: () => []
|
customObjects: () => []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const search = ref()
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
// TODO (wvffle): Make sure everything is it's own type
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
|
@ -83,8 +86,6 @@ const actions = computed(() => [
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
const emit = defineEmits(['fetch-start'])
|
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
emit('fetch-start')
|
emit('fetch-start')
|
||||||
|
|
|
@ -11,7 +11,7 @@ import useSharedLabels from '~/composables/locale/useSharedLabels'
|
||||||
|
|
||||||
const PRIVACY_LEVELS = ['me', 'instance', 'everyone'] as PrivacyLevel[]
|
const PRIVACY_LEVELS = ['me', 'instance', 'everyone'] as PrivacyLevel[]
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'updated', data: Library): void
|
(e: 'updated', data: Library): void
|
||||||
(e: 'created', data: Library): void
|
(e: 'created', data: Library): void
|
||||||
(e: 'deleted'): void
|
(e: 'deleted'): void
|
||||||
|
@ -21,7 +21,7 @@ interface Props {
|
||||||
library?: Library
|
library?: Library
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
|
@ -13,6 +13,10 @@ import RadioButton from '~/components/radios/Button.vue'
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useReport from '~/composables/moderation/useReport'
|
import useReport from '~/composables/moderation/useReport'
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'followed'): void
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
initialLibrary: Library
|
initialLibrary: Library
|
||||||
displayFollow?: boolean
|
displayFollow?: boolean
|
||||||
|
@ -20,6 +24,7 @@ interface Props {
|
||||||
displayCopyFid?: boolean
|
displayCopyFid?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
displayFollow: true,
|
displayFollow: true,
|
||||||
displayScan: true,
|
displayScan: true,
|
||||||
|
@ -68,7 +73,6 @@ const launchScan = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits(['followed', 'deleted'])
|
|
||||||
const follow = async () => {
|
const follow = async () => {
|
||||||
isLoadingFollow.value = true
|
isLoadingFollow.value = true
|
||||||
try {
|
try {
|
||||||
|
@ -76,7 +80,7 @@ const follow = async () => {
|
||||||
library.value.follow = response.data
|
library.value.follow = response.data
|
||||||
emit('followed')
|
emit('followed')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// TODO (wvffle): ==> CORRECTLY HANDLED ERROR HERE <==
|
console.error(error)
|
||||||
store.commit('ui/addMessage', {
|
store.commit('ui/addMessage', {
|
||||||
// TODO (wvffle): Translate
|
// TODO (wvffle): Translate
|
||||||
content: 'Cannot follow remote library: ' + error,
|
content: 'Cannot follow remote library: ' + error,
|
||||||
|
|
|
@ -6,11 +6,11 @@ import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
interface Emits {
|
interface Events {
|
||||||
(e: 'scanned', data: object): void
|
(e: 'scanned', data: object): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Events>()
|
||||||
|
|
||||||
const { $pgettext } = useGettext()
|
const { $pgettext } = useGettext()
|
||||||
|
|
||||||
|
|
|
@ -35,18 +35,13 @@ const fetchData = async () => {
|
||||||
|
|
||||||
fetchData()
|
fetchData()
|
||||||
|
|
||||||
// TODO (wvffle): Find correct type
|
|
||||||
const updateApproved = async (follow: LibraryFollow, approved: boolean) => {
|
const updateApproved = async (follow: LibraryFollow, approved: boolean) => {
|
||||||
follow.isLoading = true
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await axios.post(`federation/follows/library/${follow.uuid}/${approved ? 'accept' : 'reject'}/`)
|
await axios.post(`federation/follows/library/${follow.uuid}/${approved ? 'accept' : 'reject'}/`)
|
||||||
follow.approved = approved
|
follow.approved = approved
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
useErrorHandler(error as Error)
|
useErrorHandler(error as Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
follow.isLoading = false
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -85,7 +80,7 @@ const updateApproved = async (follow: LibraryFollow, approved: boolean) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table
|
<table
|
||||||
v-else-if="follows?.count > 0"
|
v-else-if="(follows ?? { count: 0 }).count > 0"
|
||||||
class="ui table"
|
class="ui table"
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// TODO (wvffle): Rename to LibraryBase
|
|
||||||
import type { Library } from '~/types'
|
import type { Library } from '~/types'
|
||||||
|
|
||||||
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
|
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
|
|
@ -32,7 +32,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
scope: 'all'
|
scope: 'all'
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO (wvffle): Make sure everything is it's own type
|
|
||||||
const page = ref(+props.defaultPage)
|
const page = ref(+props.defaultPage)
|
||||||
type ResponseType = { count: number, results: any[] }
|
type ResponseType = { count: number, results: any[] }
|
||||||
const result = ref<null | ResponseType>(null)
|
const result = ref<null | ResponseType>(null)
|
||||||
|
|
Loading…
Reference in New Issue