Merge remote-tracking branch 'upstream/develop' into user-profile-overhault

* upstream/develop:
  Fix style
  Add a way to get new captcha on click
  Fix style
  Separate captcha into the backendInteractor
  more visual fixes
  changed bottom-shadow hiding method to be more compatible with overflow
  small fix for overflowing tab-switcher
  Support disabling captcha
  Base support for CAPTCHA (kocaptcha)
This commit is contained in:
Henry Jameson 2018-12-17 19:18:35 +03:00
commit 292ac59d08
7 changed files with 72 additions and 26 deletions

View File

@ -11,7 +11,8 @@ const registration = {
username: '', username: '',
password: '', password: '',
confirm: '' confirm: ''
} },
captcha: {}
}), }),
validations: { validations: {
user: { user: {
@ -29,6 +30,8 @@ const registration = {
if ((!this.registrationOpen && !this.token) || this.signedIn) { if ((!this.registrationOpen && !this.token) || this.signedIn) {
this.$router.push('/main/all') this.$router.push('/main/all')
} }
this.setCaptcha()
}, },
computed: { computed: {
token () { return this.$route.params.token }, token () { return this.$route.params.token },
@ -41,10 +44,12 @@ const registration = {
}) })
}, },
methods: { methods: {
...mapActions(['signUp']), ...mapActions(['signUp', 'getCaptcha']),
async submit () { async submit () {
this.user.nickname = this.user.username this.user.nickname = this.user.username
this.user.token = this.token this.user.token = this.token
this.user.captcha_solution = this.captcha.solution
this.user.captcha_token = this.captcha.token
this.$v.$touch() this.$v.$touch()
@ -56,6 +61,9 @@ const registration = {
console.warn('Registration failed: ' + error) console.warn('Registration failed: ' + error)
} }
} }
},
setCaptcha () {
this.getCaptcha().then(cpt => { this.captcha = cpt })
} }
} }
} }

View File

@ -75,6 +75,19 @@
</ul> </ul>
</div> </div>
<div class="form-group" id="captcha-group" v-if="captcha.type != 'none'">
<template v-if="captcha.type == 'kocaptcha'">
<img v-bind:src="captcha.url" v-on:click="setCaptcha">
<sub>Click the image to get a new captcha</sub>
<label class='form--label' for='captcha-label'>CAPTCHA</label>
<input :disabled="isPending"
v-model='captcha.solution'
class='form-control' id='captcha-answer' type='text'>
</template>
</div>
<div class='form-group' v-if='token' > <div class='form-group' v-if='token' >
<label for='token'>{{$t('registration.token')}}</label> <label for='token'>{{$t('registration.token')}}</label>
<input disabled='true' v-model='token' class='form-control' id='token' type='text'> <input disabled='true' v-model='token' class='form-control' id='token' type='text'>

View File

@ -18,12 +18,18 @@ export default Vue.component('tab-switcher', {
const tabs = this.$slots.default const tabs = this.$slots.default
.filter(slot => slot.data) .filter(slot => slot.data)
.map((slot, index) => { .map((slot, index) => {
const classes = ['tab'] const classesTab = ['tab']
const classesWrapper = ['tab-wrapper']
if (index === this.active) { if (index === this.active) {
classes.push('active') classesTab.push('active')
classesWrapper.push('active')
} }
return (<button onClick={this.activateTab(index)} class={ classes.join(' ') }>{slot.data.attrs.label}</button>) return (
<div class={ classesWrapper.join(' ')}>
<button onClick={this.activateTab(index)} class={ classesTab.join(' ') }>{slot.data.attrs.label}</button>
</div>
)
}); });
const contents = this.$slots.default.filter(_=>_.data).map(( slot, index ) => { const contents = this.$slots.default.filter(_=>_.data).map(( slot, index ) => {
const active = index === this.active const active = index === this.active

View File

@ -9,31 +9,37 @@
.tabs { .tabs {
display: flex; display: flex;
position: relative; position: relative;
justify-content: center;
width: 100%; width: 100%;
overflow-y: hidden; overflow-y: hidden;
overflow-x: auto; overflow-x: auto;
padding-top: 5px; padding-top: 5px;
height: 32px;
box-sizing: border-box; box-sizing: border-box;
&::after, &::before { &::after, &::before {
display: block; display: block;
content: ''; content: '';
flex: 1 1 auto; flex: 1 1 auto;
}
.tab, &::after, &::before {
border-bottom: 1px solid; border-bottom: 1px solid;
border-bottom-color: $fallback--border; border-bottom-color: $fallback--border;
border-bottom-color: var(--border, $fallback--border); border-bottom-color: var(--border, $fallback--border);
} }
.tab-wrapper {
height: 28px;
overflow: hidden;
position: relative;
display: flex;
flex: 0 0 auto;
.tab { .tab {
width: 100%;
min-width: 1px;
position: relative; position: relative;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
padding: 5px 1em 99px; padding: 6px 1em;
padding-bottom: 99px;
margin-bottom: 6px - 99px;
white-space: nowrap; white-space: nowrap;
&:not(.active) { &:not(.active) {
@ -42,24 +48,28 @@
&:hover { &:hover {
z-index: 6; z-index: 6;
} }
}
&.active {
background: transparent;
z-index: 5;
}
}
&:not(.active) {
&::after { &::after {
content: ''; content: '';
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
top: 26px; bottom: 0;
z-index: 7;
border-bottom: 1px solid; border-bottom: 1px solid;
border-bottom-color: $fallback--border; border-bottom-color: $fallback--border;
border-bottom-color: var(--border, $fallback--border); border-bottom-color: var(--border, $fallback--border);
} }
} }
}
&.active {
background: transparent;
border-bottom: none;
z-index: 5;
}
}
} }
} }

View File

@ -159,6 +159,10 @@ const users = {
throw Error(errors) throw Error(errors)
} }
}, },
async getCaptcha (store) {
return await store.rootState.api.backendInteractor.getCaptcha()
},
logout (store) { logout (store) {
store.commit('clearCurrentUser') store.commit('clearCurrentUser')
store.commit('setToken', false) store.commit('setToken', false)

View File

@ -167,6 +167,8 @@ const register = (params) => {
}) })
} }
const getCaptcha = () => fetch('/api/pleroma/captcha').then(resp => resp.json())
const authHeaders = (accessToken) => { const authHeaders = (accessToken) => {
if (accessToken) { if (accessToken) {
return { 'Authorization': `Bearer ${accessToken}` } return { 'Authorization': `Bearer ${accessToken}` }
@ -496,6 +498,7 @@ const apiService = {
setUserMute, setUserMute,
fetchMutes, fetchMutes,
register, register,
getCaptcha,
updateAvatar, updateAvatar,
updateBg, updateBg,
updateProfile, updateProfile,

View File

@ -71,6 +71,7 @@ const backendInteractorService = (credentials) => {
const fetchMutes = () => apiService.fetchMutes({credentials}) const fetchMutes = () => apiService.fetchMutes({credentials})
const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials}) const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials})
const getCaptcha = () => apiService.getCaptcha()
const register = (params) => apiService.register(params) const register = (params) => apiService.register(params)
const updateAvatar = ({params}) => apiService.updateAvatar({credentials, params}) const updateAvatar = ({params}) => apiService.updateAvatar({credentials, params})
const updateBg = ({params}) => apiService.updateBg({credentials, params}) const updateBg = ({params}) => apiService.updateBg({credentials, params})
@ -100,6 +101,7 @@ const backendInteractorService = (credentials) => {
setUserMute, setUserMute,
fetchMutes, fetchMutes,
register, register,
getCaptcha,
updateAvatar, updateAvatar,
updateBg, updateBg,
updateBanner, updateBanner,