Migrate signup
This commit is contained in:
parent
14a61d5fe4
commit
45740d510e
|
@ -85,7 +85,7 @@ const save = async () => {
|
||||||
values[setting.identifier] = setting.value
|
values[setting.identifier] = setting.value
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch('instance/fetchSettings')
|
await store.dispatch('instance/fetchSettings')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errors.value = (error as BackendError).backendErrors
|
errors.value = (error as BackendError).backendErrors
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,13 @@ interface Props extends PlayOptionsProps {
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
tracks: () => [],
|
tracks: () => [],
|
||||||
track: () => null,
|
track: null,
|
||||||
artist: () => null,
|
artist: null,
|
||||||
playlist: () => null,
|
playlist: null,
|
||||||
album: () => null,
|
album: null,
|
||||||
library: () => null,
|
library: null,
|
||||||
channel: () => null,
|
channel: null,
|
||||||
account: () => null,
|
account: null,
|
||||||
dropdownIconClasses: () => ['dropdown'],
|
dropdownIconClasses: () => ['dropdown'],
|
||||||
playIconClass: () => 'play icon',
|
playIconClass: () => 'play icon',
|
||||||
buttonClasses: () => ['button'],
|
buttonClasses: () => ['button'],
|
||||||
|
|
|
@ -30,7 +30,7 @@ interface Props extends PlayOptionsProps {
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
showArt: true,
|
showArt: true,
|
||||||
displayActions: true,
|
displayActions: true,
|
||||||
defaultCover: () => null
|
defaultCover: null
|
||||||
})
|
})
|
||||||
|
|
||||||
const description = ref('')
|
const description = ref('')
|
||||||
|
|
|
@ -21,7 +21,7 @@ interface Props {
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
const emit = defineEmits<Emits>()
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
app: () => null,
|
app: null,
|
||||||
defaults: () => ({})
|
defaults: () => ({})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,88 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { RouteLocationRaw } from 'vue-router'
|
||||||
|
import type { BackendError, Form } from '~/types'
|
||||||
|
|
||||||
|
import { computed, reactive, ref } from 'vue'
|
||||||
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
import LoginForm from '~/components/auth/LoginForm.vue'
|
||||||
|
import PasswordInput from '~/components/forms/PasswordInput.vue'
|
||||||
|
import useLogger from '~/composables/useLogger'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
defaultInvitation?: string | null
|
||||||
|
next?: RouteLocationRaw
|
||||||
|
buttonClasses?: string
|
||||||
|
customization?: Form | null
|
||||||
|
fetchDescriptionHtml?: boolean
|
||||||
|
signupApprovalEnabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
defaultInvitation: null,
|
||||||
|
next: '/',
|
||||||
|
buttonClasses: 'success',
|
||||||
|
customization: null,
|
||||||
|
fetchDescriptionHtml: false,
|
||||||
|
signupApprovalEnabled: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const { $pgettext } = useGettext()
|
||||||
|
const logger = useLogger()
|
||||||
|
const store = useStore()
|
||||||
|
|
||||||
|
const labels = computed(() => ({
|
||||||
|
placeholder: $pgettext('Content/Signup/Form/Placeholder', 'Enter your invitation code (case insensitive)'),
|
||||||
|
usernamePlaceholder: $pgettext('Content/Signup/Form/Placeholder', 'Enter your username'),
|
||||||
|
emailPlaceholder: $pgettext('Content/Signup/Form/Placeholder', 'Enter your e-mail address')
|
||||||
|
}))
|
||||||
|
|
||||||
|
const signupRequiresApproval = computed(() => props.signupApprovalEnabled ?? store.state.instance.settings.moderation.signup_approval_enabled.value)
|
||||||
|
const formCustomization = computed(() => props.customization ?? store.state.instance.settings.moderation.signup_form_customization.value)
|
||||||
|
|
||||||
|
const payload = reactive({
|
||||||
|
username: '',
|
||||||
|
password1: '',
|
||||||
|
email: '',
|
||||||
|
invitation: props.defaultInvitation,
|
||||||
|
request_fields: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const submitted = ref(false)
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const errors = ref([] as string[])
|
||||||
|
const submit = async () => {
|
||||||
|
isLoading.value = true
|
||||||
|
errors.value = []
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post('auth/registration/', {
|
||||||
|
...payload,
|
||||||
|
password2: payload.password1
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.info('Successfully created account')
|
||||||
|
submitted.value = true
|
||||||
|
} catch (error) {
|
||||||
|
errors.value = (error as BackendError).backendErrors
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const isLoadingInstanceSetting = ref(false)
|
||||||
|
const fetchInstanceSettings = async () => {
|
||||||
|
isLoadingInstanceSetting.value = true
|
||||||
|
await store.dispatch('instance/fetchSettings')
|
||||||
|
isLoadingInstanceSetting.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchInstanceSettings()
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="submitted">
|
<div v-if="submitted">
|
||||||
<div class="ui success message">
|
<div class="ui success message">
|
||||||
|
@ -75,7 +160,7 @@
|
||||||
<input
|
<input
|
||||||
id="username-field"
|
id="username-field"
|
||||||
ref="username"
|
ref="username"
|
||||||
v-model="username"
|
v-model="payload.username"
|
||||||
name="username"
|
name="username"
|
||||||
required
|
required
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -88,7 +173,7 @@
|
||||||
<input
|
<input
|
||||||
id="email-field"
|
id="email-field"
|
||||||
ref="email"
|
ref="email"
|
||||||
v-model="email"
|
v-model="payload.email"
|
||||||
name="email"
|
name="email"
|
||||||
required
|
required
|
||||||
type="email"
|
type="email"
|
||||||
|
@ -98,7 +183,7 @@
|
||||||
<div class="required field">
|
<div class="required field">
|
||||||
<label for="password-field"><translate translate-context="*/*/*">Password</translate></label>
|
<label for="password-field"><translate translate-context="*/*/*">Password</translate></label>
|
||||||
<password-input
|
<password-input
|
||||||
v-model="password"
|
v-model="payload.password1"
|
||||||
field-id="password-field"
|
field-id="password-field"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,7 +194,7 @@
|
||||||
<label for="invitation-code"><translate translate-context="Content/*/Input.Label">Invitation code</translate></label>
|
<label for="invitation-code"><translate translate-context="Content/*/Input.Label">Invitation code</translate></label>
|
||||||
<input
|
<input
|
||||||
id="invitation-code"
|
id="invitation-code"
|
||||||
v-model="invitation"
|
v-model="payload.invitation"
|
||||||
required
|
required
|
||||||
type="text"
|
type="text"
|
||||||
name="invitation"
|
name="invitation"
|
||||||
|
@ -126,16 +211,16 @@
|
||||||
<textarea
|
<textarea
|
||||||
v-if="field.input_type === 'long_text'"
|
v-if="field.input_type === 'long_text'"
|
||||||
:id="`custom-field-${idx}`"
|
:id="`custom-field-${idx}`"
|
||||||
v-model="customFields[field.label]"
|
v-model="payload.request_fields[field.label]"
|
||||||
:required="field.required || null"
|
:required="field.required"
|
||||||
rows="5"
|
rows="5"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
v-else
|
v-else
|
||||||
:id="`custom-field-${idx}`"
|
:id="`custom-field-${idx}`"
|
||||||
v-model="customFields[field.label]"
|
v-model="payload.request_fields[field.label]"
|
||||||
type="text"
|
type="text"
|
||||||
:required="field.required || null"
|
:required="field.required"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -149,100 +234,3 @@
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
import LoginForm from '~/components/auth/LoginForm.vue'
|
|
||||||
import PasswordInput from '~/components/forms/PasswordInput.vue'
|
|
||||||
import useLogger from '~/composables/useLogger'
|
|
||||||
|
|
||||||
const logger = useLogger()
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
LoginForm,
|
|
||||||
PasswordInput
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
defaultInvitation: { type: String, required: false, default: null },
|
|
||||||
next: { type: String, default: '/' },
|
|
||||||
buttonClasses: { type: String, default: 'success' },
|
|
||||||
customization: { type: Object, default: null }, // ts type: Form
|
|
||||||
fetchDescriptionHtml: { type: Boolean, default: false },
|
|
||||||
signupApprovalEnabled: { type: Boolean, default: null, required: false }
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
username: '',
|
|
||||||
email: '',
|
|
||||||
password: '',
|
|
||||||
isLoadingInstanceSetting: true,
|
|
||||||
errors: [],
|
|
||||||
isLoading: false,
|
|
||||||
invitation: this.defaultInvitation,
|
|
||||||
customFields: {},
|
|
||||||
submitted: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
labels () {
|
|
||||||
const placeholder = this.$pgettext(
|
|
||||||
'Content/Signup/Form/Placeholder',
|
|
||||||
'Enter your invitation code (case insensitive)'
|
|
||||||
)
|
|
||||||
const usernamePlaceholder = this.$pgettext('Content/Signup/Form/Placeholder', 'Enter your username')
|
|
||||||
const emailPlaceholder = this.$pgettext('Content/Signup/Form/Placeholder', 'Enter your e-mail address')
|
|
||||||
return {
|
|
||||||
usernamePlaceholder,
|
|
||||||
emailPlaceholder,
|
|
||||||
placeholder
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formCustomization () {
|
|
||||||
return this.customization || this.$store.state.instance.settings.moderation.signup_form_customization.value
|
|
||||||
},
|
|
||||||
signupRequiresApproval () {
|
|
||||||
if (this.signupApprovalEnabled === null) {
|
|
||||||
return this.$store.state.instance.settings.moderation.signup_approval_enabled.value
|
|
||||||
}
|
|
||||||
return this.signupApprovalEnabled
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
const self = this
|
|
||||||
// TODO (wvffle): Await action result and remove callback from the instance store
|
|
||||||
this.$store.dispatch('instance/fetchSettings', {
|
|
||||||
callback: function () {
|
|
||||||
self.isLoadingInstanceSetting = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
submit () {
|
|
||||||
const self = this
|
|
||||||
self.isLoading = true
|
|
||||||
this.errors = []
|
|
||||||
const payload = {
|
|
||||||
username: this.username,
|
|
||||||
password1: this.password,
|
|
||||||
password2: this.password,
|
|
||||||
email: this.email,
|
|
||||||
invitation: this.invitation,
|
|
||||||
request_fields: this.customFields
|
|
||||||
}
|
|
||||||
return axios.post('auth/registration/', payload).then(
|
|
||||||
response => {
|
|
||||||
logger.info('Successfully created account')
|
|
||||||
self.submitted = true
|
|
||||||
self.isLoading = false
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
self.errors = error.backendErrors
|
|
||||||
self.isLoading = false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ export const install: InitModule = async ({ store, router }) => {
|
||||||
|
|
||||||
const url = urlParams.get('_url')
|
const url = urlParams.get('_url')
|
||||||
if (url) {
|
if (url) {
|
||||||
return router.replace(url)
|
router.replace(url)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!store.state.instance.instanceUrl) {
|
if (!store.state.instance.instanceUrl) {
|
||||||
|
|
|
@ -163,8 +163,7 @@ const store: Module<State, RootState> = {
|
||||||
commit(`${m}/reset`, null, { root: true })
|
commit(`${m}/reset`, null, { root: true })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// Send a request to the login URL and save the returned JWT
|
async fetchSettings ({ commit }) {
|
||||||
async fetchSettings ({ commit }, payload) {
|
|
||||||
const response = await axios.get('instance/settings/')
|
const response = await axios.get('instance/settings/')
|
||||||
.catch(err => logger.error('Error while fetching settings', err.response.data))
|
.catch(err => logger.error('Error while fetching settings', err.response.data))
|
||||||
|
|
||||||
|
@ -180,7 +179,6 @@ const store: Module<State, RootState> = {
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
commit('settings', sections)
|
commit('settings', sections)
|
||||||
payload?.callback?.()
|
|
||||||
},
|
},
|
||||||
async fetchFrontSettings ({ state }) {
|
async fetchFrontSettings ({ state }) {
|
||||||
const response = await axios.get(`${import.meta.env.BASE_URL}settings.json`)
|
const response = await axios.get(`${import.meta.env.BASE_URL}settings.json`)
|
||||||
|
|
Loading…
Reference in New Issue