Fix router warnings

This commit is contained in:
wvffle 2022-06-30 22:07:54 +00:00 committed by Georg Krause
parent dbe762d71c
commit e608089557
5 changed files with 144 additions and 170 deletions

View File

@ -1,3 +1,51 @@
<script setup lang="ts">
import Modal from '~/components/semantic/Modal.vue'
import ChannelUploadForm from '~/components/channels/UploadForm.vue'
import { humanSize } from '~/utils/filters'
import { useRouter } from 'vue-router'
import { useStore } from '~/store'
import { ref, computed } from 'vue'
import { useGettext } from 'vue3-gettext'
const store = useStore()
const router = useRouter()
router.beforeEach(() => store.commit('channels/showUploadModal', { show: false }))
const update = (value: boolean) => store.commit('channels/showUploadModal', { show: value })
const { $npgettext, $gettext } = useGettext()
const statusData = ref()
const statusInfo = computed(() => {
if (!statusData.value) {
return []
}
const info = []
if (statusData.value.totalSize) {
info.push(humanSize(statusData.value.totalSize))
}
if (statusData.value.totalFiles) {
const msg = $npgettext('*/*/*', '%{ count } file', '%{ count } files', statusData.value.totalFiles)
info.push($gettext(msg, { count: statusData.value.totalFiles }))
}
if (statusData.value.progress) {
info.push(`${statusData.value.progress}%`)
}
if (statusData.value.speed) {
info.push(`${humanSize(statusData.value.speed)}/s`)
}
return info
})
const step = ref(1)
const isLoading = ref(false)
</script>
<template>
<modal
v-model:show="$store.state.channels.showUploadModal"
@ -37,7 +85,6 @@
@loading="isLoading = $event"
@published="$store.commit('channels/publish', $event)"
@status="statusData = $event"
@submittable="submittable = $event"
/>
</div>
<div class="actions">
@ -96,7 +143,7 @@
<button
:class="['ui', 'primary button', {loading: isLoading}]"
type="submit"
:disabled="!statusData || !statusData.canSubmit || null"
:disabled="!statusData?.canSubmit || undefined"
@click.prevent.stop="$refs.uploadForm.publish"
>
<translate translate-context="*/Channels/Button.Label">
@ -107,7 +154,7 @@
ref="dropdown"
v-dropdown
class="ui floating dropdown icon button"
:disabled="!statusData || !statusData.canSubmit || null"
:disabled="!statusData?.canSubmit || undefined"
>
<i class="dropdown icon" />
<div class="menu">
@ -135,67 +182,3 @@
</div>
</modal>
</template>
<script>
import Modal from '~/components/semantic/Modal.vue'
import ChannelUploadForm from '~/components/channels/UploadForm.vue'
import { humanSize } from '~/utils/filters'
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
export default {
components: {
Modal,
ChannelUploadForm
},
setup () {
const guard = () => {
this.$store.commit('channels/showUploadModal', { show: false })
}
onBeforeRouteUpdate(guard)
onBeforeRouteLeave(guard)
return { humanSize }
},
data () {
return {
step: 1,
isLoading: false,
submittable: true,
statusData: null
}
},
computed: {
labels () {
return {}
},
statusInfo () {
if (!this.statusData) {
return []
}
const info = []
if (this.statusData.totalSize) {
info.push(humanSize(this.statusData.totalSize))
}
if (this.statusData.totalFiles) {
const msg = this.$npgettext('*/*/*', '%{ count } file', '%{ count } files', this.statusData.totalFiles)
info.push(
this.$gettextInterpolate(msg, { count: this.statusData.totalFiles })
)
}
if (this.statusData.progress) {
info.push(`${this.statusData.progress}%`)
}
if (this.statusData.speed) {
info.push(`${humanSize(this.statusData.speed)}/s`)
}
return info
}
},
methods: {
update (v) {
this.$store.commit('channels/showUploadModal', { show: v })
}
}
}
</script>

View File

@ -26,7 +26,7 @@ const value = useVModel(props, 'modelValue', emit)
const attachment = ref()
const isLoading = ref(false)
const errors = reactive<string[]>([])
const errors = reactive([] as Error[])
const attachmentId = Math.random().toString(36).substring(7)
const input = ref()

View File

@ -1,3 +1,82 @@
<script setup lang="ts">
import { filter, sortBy, flow } from 'lodash-es'
import axios, { AxiosError } from 'axios'
import { useGettext } from 'vue3-gettext'
import Modal from '~/components/semantic/Modal.vue'
import PlaylistForm from '~/components/playlists/Form.vue'
import useLogger from '~/composables/useLogger'
import { useStore } from '~/store'
import { ref, computed, watch } from 'vue'
import { BackendError, Playlist } from '~/types'
import { useRouter } from 'vue-router'
const logger = useLogger()
const store = useStore()
const showDuplicateTrackAddConfirmation = ref(false)
const router = useRouter()
router.beforeEach(() => {
store.commit('playlists/showModal', false)
showDuplicateTrackAddConfirmation.value = false
})
const playlists = computed(() => store.state.playlists.playlists)
const track = computed(() => store.state.playlists.modalTrack)
const { $pgettext } = useGettext()
const labels = computed(() => ({
addToPlaylist: $pgettext('Popup/Playlist/Table.Button.Tooltip/Verb', 'Add to this playlist'),
filterPlaylistField: $pgettext('Popup/Playlist/Form/Placeholder', 'Enter playlist name')
}))
const playlistNameFilter = ref('')
const sortedPlaylists = computed(() => flow(
filter((playlist: Playlist) => playlist.name.match(new RegExp(playlistNameFilter.value, 'i')) !== null),
sortBy((playlist: Playlist) => { return playlist.modification_date })
)(playlists.value).reverse())
const formKey = ref(new Date().toString())
watch(() => store.state.playlists.showModal, () => {
formKey.value = new Date().toString()
showDuplicateTrackAddConfirmation.value = false
})
const lastSelectedPlaylist = ref(-1)
const errors = ref([] as AxiosError[])
const duplicateTrackAddInfo = ref({} as { playlist_name?: string })
const addToPlaylist = async (playlistId: number, allowDuplicates: boolean) => {
lastSelectedPlaylist.value = playlistId
try {
await axios.post(`playlists/${playlistId}/add`, {
tracks: [track.value?.id].filter(i => i),
allow_duplicates: allowDuplicates
})
logger.info('Successfully added track to playlist')
store.state.playlists.showModal = false
store.dispatch('playlists/fetchOwn')
} catch (error) {
if (error as BackendError) {
const { backendErrors } = error as BackendError
if (backendErrors.length === 1 && backendErrors[0].code === 'tracks_already_exist_in_playlist') {
duplicateTrackAddInfo.value = backendErrors[0] as unknown as { playlist_name: string }
showDuplicateTrackAddConfirmation.value = true
} else {
errors.value = backendErrors
showDuplicateTrackAddConfirmation.value = false
}
}
}
}
</script>
<template>
<modal
v-model:show="$store.state.playlists.showModal"
@ -35,15 +114,15 @@
class="ui warning message"
>
<p
v-translate="{track: track.title, playlist: duplicateTrackAddInfo.playlist_name}"
v-translate="{track: track?.title, playlist: duplicateTrackAddInfo.playlist_name}"
translate-context="Popup/Playlist/Paragraph"
:translate-params="{track: track.title, playlist: duplicateTrackAddInfo.playlist_name}"
:translate-params="{track: track?.title, playlist: duplicateTrackAddInfo.playlist_name}"
>
<strong>%{ track }</strong> is already in <strong>%{ playlist }</strong>.
</p>
<button
class="ui small basic cancel button"
@click="duplicateTrackAddConfirm(false)"
@click="showDuplicateTrackAddConfirmation = false"
>
<translate translate-context="*/*/Button.Label/Verb">
Cancel
@ -189,98 +268,3 @@
</div>
</modal>
</template>
<script>
import { filter, sortBy, flow } from 'lodash-es'
import axios from 'axios'
import { mapState } from 'vuex'
import Modal from '~/components/semantic/Modal.vue'
import PlaylistForm from '~/components/playlists/Form.vue'
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import useLogger from '~/composables/useLogger'
const logger = useLogger()
export default {
components: {
Modal,
PlaylistForm
},
setup () {
const guard = () => {
this.$store.commit('playlists/showModal', false)
this.showDuplicateTrackAddConfirmation = false
}
onBeforeRouteUpdate(guard)
onBeforeRouteLeave(guard)
},
data () {
return {
formKey: String(new Date()),
errors: [],
playlistNameFilter: '',
duplicateTrackAddInfo: {},
showDuplicateTrackAddConfirmation: false,
lastSelectedPlaylist: -1
}
},
computed: {
...mapState({
playlists: state => state.playlists.playlists,
track: state => state.playlists.modalTrack
}),
labels () {
return {
addToPlaylist: this.$pgettext('Popup/Playlist/Table.Button.Tooltip/Verb', 'Add to this playlist'),
filterPlaylistField: this.$pgettext('Popup/Playlist/Form/Placeholder', 'Enter playlist name')
}
},
sortedPlaylists () {
const regexp = new RegExp(this.playlistNameFilter, 'i')
const p = flow(
filter((e) => e.name.match(regexp) !== null),
sortBy((e) => { return e.modification_date })
)(this.playlists)
p.reverse()
return p
}
},
watch: {
'$store.state.playlists.showModal' () {
this.formKey = String(new Date())
this.showDuplicateTrackAddConfirmation = false
}
},
methods: {
addToPlaylist (playlistId, allowDuplicate) {
const self = this
const payload = {
tracks: [this.track.id],
allow_duplicates: allowDuplicate
}
self.lastSelectedPlaylist = playlistId
return axios.post(`playlists/${playlistId}/add`, payload).then(response => {
logger.info('Successfully added track to playlist')
self.$store.state.playlists.showModal = false
self.$store.dispatch('playlists/fetchOwn')
}, error => {
if (error.backendErrors.length === 1 && error.backendErrors[0].code === 'tracks_already_exist_in_playlist') {
self.duplicateTrackAddInfo = error.backendErrors[0]
self.showDuplicateTrackAddConfirmation = true
} else {
self.errors = error.backendErrors
self.showDuplicateTrackAddConfirmation = false
}
})
},
duplicateTrackAddConfirm (v) {
this.showDuplicateTrackAddConfirmation = v
}
}
}
</script>

View File

@ -1,11 +1,12 @@
import axios from 'axios'
import { Module } from 'vuex'
import { RootState } from '~/store/index'
import { Playlist, Track } from '~/types'
export interface State {
playlists: any[]
playlists: Playlist[]
showModal: boolean
modalTrack: null
modalTrack: null | Track
}
const store: Module<State, RootState> = {

View File

@ -87,13 +87,19 @@ export interface License {
url: string
}
export interface Playlist {
id: string
name: string
modification_date: Date // TODO (wvffle): Find correct type
}
// API stuff
export interface APIErrorResponse {
[key: string]: APIErrorResponse | string[]
}
export interface BackendError extends AxiosError {
backendErrors: string[]
export interface BackendError {
backendErrors: AxiosError[]
rawPayload?: object
}