Fetch inbox data
This commit is contained in:
parent
9d8465c950
commit
6b179885ce
|
@ -96,12 +96,18 @@ const moderationNotifications = computed(() =>
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (store.state.auth.authenticated) {
|
if (store.state.auth.authenticated) {
|
||||||
const [edits, reports, requests] = await Promise.all([
|
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('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/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 } }))
|
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', {
|
store.commit('ui/incrementNotifications', {
|
||||||
type: 'pendingReviewEdits',
|
type: 'pendingReviewEdits',
|
||||||
value: edits.data.count
|
value: edits.data.count
|
||||||
|
|
|
@ -1,10 +1,83 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { BackendError } from '~/types'
|
||||||
|
|
||||||
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
|
import PasswordInput from '~/components/forms/PasswordInput.vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
next?: string
|
||||||
|
buttonClasses?: string
|
||||||
|
showSignup?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
next: '/library',
|
||||||
|
buttonClasses: 'success',
|
||||||
|
showSignup: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const domain = location.hostname
|
||||||
|
const { $pgettext } = useGettext()
|
||||||
|
const store = useStore()
|
||||||
|
|
||||||
|
const credentials = reactive({
|
||||||
|
username: '',
|
||||||
|
password: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const labels = computed(() => ({
|
||||||
|
usernamePlaceholder: $pgettext('Content/Login/Input.Placeholder', 'Enter your username or e-mail address')
|
||||||
|
}))
|
||||||
|
|
||||||
|
const username = ref()
|
||||||
|
onMounted(() => username.value.focus())
|
||||||
|
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const errors = ref([] as string[])
|
||||||
|
const submit = async () => {
|
||||||
|
isLoading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (domain === store.getters['instance/domain']) {
|
||||||
|
await store.dispatch('auth/login', {
|
||||||
|
credentials,
|
||||||
|
next: props.next
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await store.dispatch('auth/oauthLogin', props.next)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const backendError = error as BackendError
|
||||||
|
|
||||||
|
if (backendError.response?.status === 400) {
|
||||||
|
errors.value = ['invalid_credentials']
|
||||||
|
} else {
|
||||||
|
errors.value = backendError.backendErrors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// export default {
|
||||||
|
// created () {
|
||||||
|
// if (this.$store.state.auth.authenticated) {
|
||||||
|
// this.$router.push(this.next)
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<form
|
<form
|
||||||
class="ui form"
|
class="ui form"
|
||||||
@submit.prevent="submit()"
|
@submit.prevent="submit()"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="error"
|
v-if="errors.length > 0"
|
||||||
role="alert"
|
role="alert"
|
||||||
class="ui negative message"
|
class="ui negative message"
|
||||||
>
|
>
|
||||||
|
@ -14,18 +87,18 @@
|
||||||
</translate>
|
</translate>
|
||||||
</h4>
|
</h4>
|
||||||
<ul class="list">
|
<ul class="list">
|
||||||
<li v-if="error == 'invalid_credentials' && $store.state.instance.settings.moderation.signup_approval_enabled.value">
|
<li v-if="errors[0] == 'invalid_credentials' && $store.state.instance.settings.moderation.signup_approval_enabled.value">
|
||||||
<translate translate-context="Content/Login/Error message.List item/Call to action">
|
<translate translate-context="Content/Login/Error message.List item/Call to action">
|
||||||
If you signed-up recently, you may need to wait before our moderation team review your account, or verify your e-mail address.
|
If you signed-up recently, you may need to wait before our moderation team review your account, or verify your e-mail address.
|
||||||
</translate>
|
</translate>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="error == 'invalid_credentials'">
|
<li v-else-if="errors[0] == 'invalid_credentials'">
|
||||||
<translate translate-context="Content/Login/Error message.List item/Call to action">
|
<translate translate-context="Content/Login/Error message.List item/Call to action">
|
||||||
Please double-check that your username and password combination is correct and make sure you verified your e-mail address.
|
Please double-check that your username and password combination is correct and make sure you verified your e-mail address.
|
||||||
</translate>
|
</translate>
|
||||||
</li>
|
</li>
|
||||||
<li v-else>
|
<li v-else>
|
||||||
{{ error }}
|
{{ errors[0] }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -88,82 +161,3 @@
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import PasswordInput from '~/components/forms/PasswordInput.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
PasswordInput
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
next: { type: String, default: '/library' },
|
|
||||||
buttonClasses: { type: String, default: 'success' },
|
|
||||||
showSignup: { type: Boolean, default: true }
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
// We need to initialize the component with any
|
|
||||||
// properties that will be used in it
|
|
||||||
credentials: {
|
|
||||||
username: '',
|
|
||||||
password: ''
|
|
||||||
},
|
|
||||||
error: '',
|
|
||||||
isLoading: false,
|
|
||||||
domain: location.hostname
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
labels () {
|
|
||||||
const usernamePlaceholder = this.$pgettext('Content/Login/Input.Placeholder', 'Enter your username or e-mail address')
|
|
||||||
return {
|
|
||||||
usernamePlaceholder
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
if (this.$store.state.auth.authenticated) {
|
|
||||||
this.$router.push(this.next)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
if (this.$refs.username) {
|
|
||||||
this.$refs.username.focus()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async submit () {
|
|
||||||
if (location.hostname === this.$store.getters['instance/domain']) {
|
|
||||||
return await this.submitSession()
|
|
||||||
} else {
|
|
||||||
this.isLoading = true
|
|
||||||
await this.$store.dispatch('auth/oauthLogin', this.next)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async submitSession () {
|
|
||||||
this.isLoading = true
|
|
||||||
this.error = ''
|
|
||||||
const credentials = {
|
|
||||||
username: this.credentials.username,
|
|
||||||
password: this.credentials.password
|
|
||||||
}
|
|
||||||
this.$store
|
|
||||||
.dispatch('auth/login', {
|
|
||||||
credentials,
|
|
||||||
next: this.next,
|
|
||||||
onError: error => {
|
|
||||||
if (error.response.status === 400) {
|
|
||||||
self.error = 'invalid_credentials'
|
|
||||||
} else {
|
|
||||||
self.error = error.backendErrors[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
self.isLoading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import type { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'
|
import type { NavigationGuardNext, RouteLocationNamedRaw, RouteLocationNormalized } from 'vue-router'
|
||||||
import type { Permission } from '~/store/auth'
|
import type { Permission } from '~/store/auth'
|
||||||
|
|
||||||
import store from '~/store'
|
import store from '~/store'
|
||||||
|
@ -12,3 +12,13 @@ export const hasPermissions = (permission: Permission) => (to: RouteLocationNorm
|
||||||
console.log('Not authenticated. Redirecting to library.')
|
console.log('Not authenticated. Redirecting to library.')
|
||||||
next({ name: 'library.index' })
|
next({ name: 'library.index' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const requireLoggedIn = (fallbackLocation: RouteLocationNamedRaw) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
|
||||||
|
if (store.state.auth.authenticated) return next()
|
||||||
|
return next(fallbackLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const requireLoggedOut = (fallbackLocation: RouteLocationNamedRaw) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
|
||||||
|
if (!store.state.auth.authenticated) return next()
|
||||||
|
return next(fallbackLocation)
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import type { RouteRecordRaw } from 'vue-router'
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
|
import { requireLoggedOut } from '../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
|
// 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' })
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/auth/password/reset',
|
path: '/auth/password/reset',
|
||||||
|
|
Loading…
Reference in New Issue