Fetch all user info on startup
This commit is contained in:
parent
bd1a92c5f1
commit
4c02478470
|
@ -67,6 +67,11 @@ onKeyboardShortcut('h', () => toggleShortcutsModal())
|
||||||
|
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
const showSetInstanceModal = ref(false)
|
const showSetInstanceModal = ref(false)
|
||||||
|
|
||||||
|
// Fetch user data on startup
|
||||||
|
if (store.state.auth.authenticated) {
|
||||||
|
store.dispatch('auth/fetchUser')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -9,7 +9,6 @@ import SemanticModal from '~/components/semantic/Modal.vue'
|
||||||
|
|
||||||
import useThemeList from '~/composables/useThemeList'
|
import useThemeList from '~/composables/useThemeList'
|
||||||
import useTheme from '~/composables/useTheme'
|
import useTheme from '~/composables/useTheme'
|
||||||
import axios from 'axios'
|
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { computed, ref, watch, watchEffect, onMounted } from 'vue'
|
import { computed, ref, watch, watchEffect, onMounted } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
@ -94,37 +93,6 @@ const moderationNotifications = computed(() =>
|
||||||
+ store.state.ui.notifications.pendingReviewRequests
|
+ store.state.ui.notifications.pendingReviewRequests
|
||||||
)
|
)
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
if (store.state.auth.authenticated) {
|
|
||||||
const [inbox, edits, reports, requests] = await Promise.all([
|
|
||||||
axios.get('federation/inbox/', { params: { is_read: false } }).catch(() => ({ data: { count: 0 } })),
|
|
||||||
axios.get('mutations/', { params: { page_size: 1, q: 'is_approved:null' } }).catch(() => ({ data: { count: 0 } })),
|
|
||||||
axios.get('manage/moderation/reports/', { params: { page_size: 1, q: 'resolved:no' } }).catch(() => ({ data: { count: 0 } })),
|
|
||||||
axios.get('manage/moderation/requests/', { params: { page_size: 1, q: 'status:pending' } }).catch(() => ({ data: { count: 0 } }))
|
|
||||||
])
|
|
||||||
|
|
||||||
store.commit('ui/incrementNotifications', {
|
|
||||||
type: 'inbox',
|
|
||||||
value: inbox.data.count
|
|
||||||
})
|
|
||||||
|
|
||||||
store.commit('ui/incrementNotifications', {
|
|
||||||
type: 'pendingReviewEdits',
|
|
||||||
value: edits.data.count
|
|
||||||
})
|
|
||||||
|
|
||||||
store.commit('ui/incrementNotifications', {
|
|
||||||
type: 'pendingReviewRequests',
|
|
||||||
value: requests.data.count
|
|
||||||
})
|
|
||||||
|
|
||||||
store.commit('ui/incrementNotifications', {
|
|
||||||
type: 'pendingReviewReports',
|
|
||||||
value: reports.data.count
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const isProduction = import.meta.env.PROD
|
const isProduction = import.meta.env.PROD
|
||||||
const showUserModal = ref(false)
|
const showUserModal = ref(false)
|
||||||
const showLanguageModal = ref(false)
|
const showLanguageModal = ref(false)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { BackendError } from '~/types'
|
import type { BackendError } from '~/types'
|
||||||
|
import type { RouteLocationRaw } from 'vue-router'
|
||||||
|
|
||||||
import { ref, reactive, computed, onMounted } from 'vue'
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
@ -8,7 +9,7 @@ import { useStore } from '~/store'
|
||||||
import PasswordInput from '~/components/forms/PasswordInput.vue'
|
import PasswordInput from '~/components/forms/PasswordInput.vue'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
next?: string
|
next?: RouteLocationRaw
|
||||||
buttonClasses?: string
|
buttonClasses?: string
|
||||||
showSignup?: boolean
|
showSignup?: boolean
|
||||||
}
|
}
|
||||||
|
@ -42,10 +43,7 @@ const submit = async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (domain === store.getters['instance/domain']) {
|
if (domain === store.getters['instance/domain']) {
|
||||||
await store.dispatch('auth/login', {
|
await store.dispatch('auth/login', { credentials })
|
||||||
credentials,
|
|
||||||
next: props.next
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
await store.dispatch('auth/oauthLogin', props.next)
|
await store.dispatch('auth/oauthLogin', props.next)
|
||||||
}
|
}
|
||||||
|
@ -61,14 +59,6 @@ const submit = async () => {
|
||||||
|
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// export default {
|
|
||||||
// created () {
|
|
||||||
// if (this.$store.state.auth.authenticated) {
|
|
||||||
// this.$router.push(this.next)
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { User } from '~/types'
|
import type { User } from '~/types'
|
||||||
import type { Module } from 'vuex'
|
import type { Module } from 'vuex'
|
||||||
import type { RootState } from '~/store/index'
|
import type { RootState } from '~/store/index'
|
||||||
|
import type { RouteLocationRaw } from 'vue-router'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import useLogger from '~/composables/useLogger'
|
import useLogger from '~/composables/useLogger'
|
||||||
|
@ -147,20 +148,12 @@ const store: Module<State, RootState> = {
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
// Send a request to the login URL and save the returned JWT
|
// Send a request to the login URL and save the returned JWT
|
||||||
login ({ dispatch }, { next, credentials, onError }) {
|
async login ({ dispatch }, { credentials }) {
|
||||||
const form = useFormData(credentials)
|
const form = useFormData(credentials)
|
||||||
return axios.post('users/login', form).then(() => {
|
await axios.post('users/login', form)
|
||||||
logger.info('Successfully logged in as', credentials.username)
|
|
||||||
dispatch('fetchUser').then(() => {
|
logger.info('Successfully logged in as', credentials.username)
|
||||||
// Redirect to a specified route
|
await dispatch('fetchUser')
|
||||||
import('~/router').then((router) => {
|
|
||||||
return router.default.push(next)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}, response => {
|
|
||||||
logger.error('Error while logging in', response.data)
|
|
||||||
onError(response)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
async logout ({ commit }) {
|
async logout ({ commit }) {
|
||||||
try {
|
try {
|
||||||
|
@ -181,36 +174,40 @@ const store: Module<State, RootState> = {
|
||||||
})
|
})
|
||||||
logger.info('Log out, goodbye!')
|
logger.info('Log out, goodbye!')
|
||||||
},
|
},
|
||||||
fetchUser ({ dispatch }) {
|
|
||||||
return new Promise((resolve, reject) => {
|
async fetchNotifications ({ dispatch, state }) {
|
||||||
axios.get('users/me/').then((response) => {
|
return Promise.all([
|
||||||
logger.info('Successfully fetched user profile')
|
dispatch('ui/fetchUnreadNotifications', null, { root: true }),
|
||||||
dispatch('updateUser', response.data)
|
state.availablePermissions.library && dispatch('ui/fetchPendingReviewEdits', null, { root: true }),
|
||||||
dispatch('ui/fetchUnreadNotifications', null, { root: true })
|
state.availablePermissions.moderation && dispatch('ui/fetchPendingReviewReports', null, { root: true }),
|
||||||
if (response.data.permissions.library) {
|
state.availablePermissions.moderation && dispatch('ui/fetchPendingReviewRequests', null, { root: true })
|
||||||
dispatch('ui/fetchPendingReviewEdits', null, { root: true })
|
])
|
||||||
}
|
},
|
||||||
if (response.data.permissions.moderation) {
|
async fetchUser ({ dispatch }) {
|
||||||
dispatch('ui/fetchPendingReviewReports', null, { root: true })
|
try {
|
||||||
dispatch('ui/fetchPendingReviewRequests', null, { root: true })
|
const response = await axios.get('users/me/')
|
||||||
}
|
logger.info('Successfully fetched user profile')
|
||||||
dispatch('favorites/fetch', null, { root: true })
|
|
||||||
dispatch('channels/fetchSubscriptions', null, { root: true })
|
dispatch('updateUser', response.data)
|
||||||
dispatch('libraries/fetchFollows', null, { root: true })
|
|
||||||
|
await Promise.all([
|
||||||
|
dispatch('fetchNotifications'),
|
||||||
|
dispatch('favorites/fetch', null, { root: true }),
|
||||||
|
dispatch('playlists/fetchOwn', null, { root: true }),
|
||||||
|
dispatch('libraries/fetchFollows', null, { root: true }),
|
||||||
|
dispatch('channels/fetchSubscriptions', null, { root: true }),
|
||||||
dispatch('moderation/fetchContentFilters', null, { root: true })
|
dispatch('moderation/fetchContentFilters', null, { root: true })
|
||||||
dispatch('playlists/fetchOwn', null, { root: true })
|
])
|
||||||
resolve(response.data)
|
} catch (error) {
|
||||||
}, () => {
|
logger.error('Error while fetching user profile', error)
|
||||||
logger.info('Error while fetching user profile')
|
}
|
||||||
reject(new Error('Error while fetching user profile'))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
updateUser ({ commit }, data) {
|
updateUser ({ commit }, data) {
|
||||||
commit('authenticated', true)
|
commit('authenticated', true)
|
||||||
commit('profile', data)
|
commit('profile', data)
|
||||||
commit('username', data.username)
|
commit('username', data.username)
|
||||||
commit('fullUsername', data.full_username)
|
commit('fullUsername', data.full_username)
|
||||||
|
|
||||||
if (data.tokens) {
|
if (data.tokens) {
|
||||||
commit('scopedTokens', data.tokens)
|
commit('scopedTokens', data.tokens)
|
||||||
}
|
}
|
||||||
|
@ -220,7 +217,7 @@ const store: Module<State, RootState> = {
|
||||||
commit('permission', { key: permission, status: hasPermission })
|
commit('permission', { key: permission, status: hasPermission })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async oauthLogin ({ state, rootState, commit }, next) {
|
async oauthLogin ({ state, rootState, commit }, next: RouteLocationRaw) {
|
||||||
const app = await createOauthApp()
|
const app = await createOauthApp()
|
||||||
commit('oauthApp', app)
|
commit('oauthApp', app)
|
||||||
const redirectUri = encodeURIComponent(`${location.origin}/auth/callback`)
|
const redirectUri = encodeURIComponent(`${location.origin}/auth/callback`)
|
||||||
|
|
|
@ -103,13 +103,11 @@ const store: Module<State, RootState> = {
|
||||||
toggle ({ getters, dispatch }, uuid) {
|
toggle ({ getters, dispatch }, uuid) {
|
||||||
dispatch('set', { uuid, value: !getters.isSubscribed(uuid) })
|
dispatch('set', { uuid, value: !getters.isSubscribed(uuid) })
|
||||||
},
|
},
|
||||||
fetchSubscriptions ({ commit }) {
|
async fetchSubscriptions ({ commit }) {
|
||||||
const promise = axios.get('subscriptions/all/')
|
const response = await axios.get('subscriptions/all/')
|
||||||
return promise.then((response) => {
|
for (const result of response.data.results) {
|
||||||
response.data.results.forEach((result: { channel: unknown }) => {
|
commit('subscriptions', { uuid: result.channel, value: true })
|
||||||
commit('subscriptions', { uuid: result.channel, value: true })
|
}
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,20 +64,20 @@ const store: Module<State, RootState> = {
|
||||||
toggle ({ getters, dispatch }, id) {
|
toggle ({ getters, dispatch }, id) {
|
||||||
dispatch('set', { id, value: !getters.isFavorite(id) })
|
dispatch('set', { id, value: !getters.isFavorite(id) })
|
||||||
},
|
},
|
||||||
fetch ({ commit, rootState }) {
|
async fetch ({ commit, rootState }) {
|
||||||
// will fetch favorites by batches from API to have them locally
|
// will fetch favorites by batches from API to have them locally
|
||||||
const params = {
|
const params = {
|
||||||
user: rootState.auth.profile?.id,
|
user: rootState.auth.profile?.id,
|
||||||
page_size: 50,
|
page_size: 50,
|
||||||
ordering: '-creation_date'
|
ordering: '-creation_date'
|
||||||
}
|
}
|
||||||
const promise = axios.get('favorites/tracks/all/', { params })
|
|
||||||
return promise.then((response) => {
|
const response = await axios.get('favorites/tracks/all/', { params })
|
||||||
logger.info('Fetched a batch of ' + response.data.results.length + ' favorites')
|
logger.info('Fetched a batch of ' + response.data.results.length + ' favorites')
|
||||||
response.data.results.forEach((result: { track: string }) => {
|
|
||||||
commit('track', { id: result.track, value: true })
|
for (const result of response.data.results) {
|
||||||
})
|
commit('track', { id: result.track, value: true })
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,13 +67,11 @@ const store: Module<State, RootState> = {
|
||||||
toggle ({ getters, dispatch }, uuid) {
|
toggle ({ getters, dispatch }, uuid) {
|
||||||
dispatch('set', { uuid, value: !getters.follow(uuid) })
|
dispatch('set', { uuid, value: !getters.follow(uuid) })
|
||||||
},
|
},
|
||||||
fetchFollows ({ dispatch, state, commit, rootState }, url) {
|
async fetchFollows ({ dispatch, state, commit, rootState }, url) {
|
||||||
const promise = axios.get('federation/follows/library/all/')
|
const response = await axios.get('federation/follows/library/all/')
|
||||||
return promise.then((response) => {
|
for (const result of response.data.results) {
|
||||||
response.data.results.forEach((result: { library: string }) => {
|
commit('follows', { library: result.library, follow: result })
|
||||||
commit('follows', { library: result.library, follow: result })
|
}
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,30 +128,28 @@ const store: Module<State, RootState> = {
|
||||||
commit('reportModalTarget', payload)
|
commit('reportModalTarget', payload)
|
||||||
commit('showReportModal', true)
|
commit('showReportModal', true)
|
||||||
},
|
},
|
||||||
fetchContentFilters ({ dispatch, commit }, url) {
|
async fetchContentFilters ({ dispatch, commit }, url) {
|
||||||
let params = {}
|
const params = url
|
||||||
let promise
|
? {}
|
||||||
if (url) {
|
: {
|
||||||
promise = axios.get(url)
|
page_size: 100,
|
||||||
} else {
|
ordering: '-creation_date'
|
||||||
commit('empty')
|
}
|
||||||
params = {
|
|
||||||
page_size: 100,
|
if (!url) commit('empty')
|
||||||
ordering: '-creation_date'
|
const response = await axios.get(url ?? 'moderation/content-filters/', { params })
|
||||||
}
|
|
||||||
promise = axios.get('moderation/content-filters/', { params })
|
logger.info(`Fetched a batch of ${response.data.results.length} filters`)
|
||||||
|
|
||||||
|
for (const result of response.data.results) {
|
||||||
|
commit('contentFilter', result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.data.next) {
|
||||||
|
await dispatch('fetchContentFilters', response.data.next)
|
||||||
}
|
}
|
||||||
return promise.then((response) => {
|
|
||||||
logger.info('Fetched a batch of ' + response.data.results.length + ' filters')
|
|
||||||
if (response.data.next) {
|
|
||||||
dispatch('fetchContentFilters', response.data.next)
|
|
||||||
}
|
|
||||||
response.data.results.forEach((result: ContentFilter) => {
|
|
||||||
commit('contentFilter', result)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
deleteContentFilter ({ commit }, uuid) {
|
async deleteContentFilter ({ commit }, uuid) {
|
||||||
return axios.delete(`moderation/content-filters/${uuid}/`).then(() => {
|
return axios.delete(`moderation/content-filters/${uuid}/`).then(() => {
|
||||||
commit('deleteContentFilter', uuid)
|
commit('deleteContentFilter', uuid)
|
||||||
})
|
})
|
||||||
|
|
|
@ -41,7 +41,7 @@ const store: Module<State, RootState> = {
|
||||||
|
|
||||||
const playlists = []
|
const playlists = []
|
||||||
let url = 'playlists/'
|
let url = 'playlists/'
|
||||||
while (url != null) {
|
while (url !== null) {
|
||||||
const response = await axios.get(url, { params: { scope: 'me' } })
|
const response = await axios.get(url, { params: { scope: 'me' } })
|
||||||
playlists.push(...response.data.results)
|
playlists.push(...response.data.results)
|
||||||
url = response.data.next
|
url = response.data.next
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { useRouter } from 'vue-router'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
|
import { whenever } from '@vueuse/core'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
next?: RouteLocationRaw
|
next?: RouteLocationRaw
|
||||||
|
@ -21,11 +22,11 @@ const labels = computed(() => ({
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
if (store.state.auth.authenticated) {
|
const router = useRouter()
|
||||||
const router = useRouter()
|
whenever(() => store.state.auth.authenticated, () => {
|
||||||
const resolved = router.resolve(props.next)
|
const resolved = router.resolve(props.next)
|
||||||
router.push(resolved.name === '404' ? '/library' : props.next)
|
router.push(resolved.name === '404' ? '/library' : props.next)
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
Loading…
Reference in New Issue