Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Use new vue components in login form
- Improve accessibility
- Simply code

Signed-off-by: Carl Schwan <[email protected]>
  • Loading branch information
CarlSchwan committed Sep 5, 2022
commit df40fc91729ebd66941705637b440033036c8b8e
42 changes: 0 additions & 42 deletions core/css/guest.css
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,6 @@ form {
margin: auto;
padding: 0;
}
form fieldset {
width: 260px;
margin-top: 8px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
form #sqliteInformation {
margin-top: 0px;
margin-bottom: 20px;
Expand Down Expand Up @@ -160,9 +152,6 @@ form #datadirField legend {
.wrapper {
margin-top: 0;
}
.alternative-logins {
margin: auto;
}
}


Expand Down Expand Up @@ -262,9 +251,6 @@ input[type='email'] {
color: var(--color-text-lighter);
cursor: text;
font-family: inherit;
-webkit-appearance: textfield;
-moz-appearance: textfield;
box-sizing: content-box;
font-weight: normal;
margin-left: 0;
margin-right: 0;
Expand Down Expand Up @@ -491,34 +477,6 @@ form .warning input[type='checkbox']+label {
color: var(--color-primary-text);
}

/* Alternative Logins */
.alternative-logins legend {
margin-bottom: 10px;
}
.alternative-logins li {
height: 40px;
white-space: nowrap;
padding: 05px;
}
.alternative-logins a.button,
.alternative-logins li a {
width: 100%;
display: inline-block;
text-align: center;
box-sizing: border-box;
border: 2px solid var(--color-primary-text);
background-color: var(--color-primary);
color: var(--color-primary-text);
border-radius: 100px; /* --border-radius-pill */
}

.alternative-logins a.button:focus,
.alternative-logins li a:focus {
border: 2px solid var(--color-primary-hover);
background-image: linear-gradient(40deg, var(--color-primary) 0%, var(--color-primary-light) 100%);
background-position: initial;
}

/* fixes for update page TODO should be fixed some time in a proper way */
/* this is just for an error while updating the ownCloud instance */
.updateProgress .error {
Expand Down
134 changes: 60 additions & 74 deletions core/src/components/login/LoginForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@

<template>
<form ref="loginForm"
class="login-form"
method="post"
name="login"
:action="loginActionUrl"
@submit="submit">
<fieldset>
<fieldset class="login-form__fieldset">
<div v-if="apacheAuthFailed"
class="warning">
{{ t('core', 'Server side authentication failed!') }}<br>
Expand All @@ -52,65 +53,36 @@
<!-- the following div ensures that the spinner is always inside the #message div -->
<div style="clear: both;" />
</div>
<p class="grouptop"
:class="{shake: invalidPassword}">
<input id="user"
ref="user"
v-model="user"
type="text"
name="user"
autocapitalize="none"
autocorrect="off"
:autocomplete="autoCompleteAllowed ? 'on' : 'off'"
:placeholder="t('core', 'Username or email')"
:aria-label="t('core', 'Username or email')"
required
@change="updateUsername">
<label for="user" class="infield">{{ t('core', 'Username or email') }}</label>
</p>

<p class="groupbottom"
:class="{shake: invalidPassword}">
<input id="password"
ref="password"
:type="passwordInputType"
class="password-with-toggle"
name="password"
autocorrect="off"
autocapitalize="none"
:autocomplete="autoCompleteAllowed ? 'current-password' : 'off'"
:placeholder="t('core', 'Password')"
:aria-label="t('core', 'Password')"
required>
<label for="password"
class="infield">{{ t('core', 'Password') }}</label>
<NcButton class="toggle-password"
type="tertiary-no-background"
:aria-label="isPasswordHidden ? t('core', 'Show password') : t('core', 'Hide password')"
@click.stop.prevent="togglePassword">
<template #icon>
<Eye v-if="isPasswordHidden" :size="20" />
<EyeOff v-else :size="20" />
</template>
</NcButton>
</p>
<NcTextField id="user"
:label="t('core', 'Username or email')"
:labelVisible="true"
ref="user"
name="user"
:class="{shake: invalidPassword}"
:value.sync="user"
autocapitalize="none"
:spellchecking="false"
:autocomplete="autoCompleteAllowed ? 'username' : 'off'"
:aria-label="t('core', 'Username or email')"
required
@change="updateUsername" />

<NcPasswordField id="password"
ref="password"
name="password"
:labelVisible="true"
:class="{shake: invalidPassword}"
:value.sync="password"
:spellchecking="false"
autocapitalize="none"
:autocomplete="autoCompleteAllowed ? 'current-password' : 'off'"
:label="t('core', 'Password')"
:helperText="errorLabel"
:error="isError"
required />

<LoginButton :loading="loading" />

<p v-if="invalidPassword"
class="warning wrongPasswordMsg">
{{ t('core', 'Wrong username or password.') }}
</p>
<p v-else-if="userDisabled"
class="warning userDisabledMsg">
{{ t('core', 'User disabled') }}
</p>

<p v-if="throttleDelay && throttleDelay > 5000"
class="warning throttledMsg">
{{ t('core', 'We have detected multiple invalid login attempts from your IP. Therefore your next login is throttled up to 30 seconds.') }}
</p>

<input v-if="redirectUrl"
type="hidden"
name="redirect_url"
Expand All @@ -136,7 +108,9 @@
import jstz from 'jstimezonedetect'
import { generateUrl, imagePath } from '@nextcloud/router'

import NcButton from '@nextcloud/vue/dist/Components/NcButton'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcPasswordField from '@nextcloud/vue/dist/Components/NcPasswordField.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import Eye from 'vue-material-design-icons/Eye'
import EyeOff from 'vue-material-design-icons/EyeOff'

Expand All @@ -150,6 +124,8 @@ export default {
Eye,
EyeOff,
LoginButton,
NcPasswordField,
NcTextField,
},

props: {
Expand Down Expand Up @@ -190,11 +166,26 @@ export default {
timezoneOffset: (-new Date().getTimezoneOffset() / 60),
user: this.username,
password: '',
passwordInputType: 'password',
}
},

computed: {
isError() {
return this.invalidPassword || this.userDisabled
|| (this.throttleDelay && this.throttleDelay > 5000)
},
errorLabel() {
if (this.invalidPassword) {
return t('core', 'Wrong username or password.')
}
if (this.userDisabled) {
return t('core', 'User disabled')
}
if (this.throttleDelay && this.throttleDelay > 5000) {
return t('core', 'We have detected multiple invalid login attempts from your IP. Therefore your next login is throttled up to 30 seconds.')
}
return undefined;
},
apacheAuthFailed() {
return this.errors.indexOf('apacheAuthFailed') !== -1
},
Expand All @@ -213,9 +204,6 @@ export default {
loginActionUrl() {
return generateUrl('login')
},
isPasswordHidden() {
return this.passwordInputType === 'password'
},
},

mounted() {
Expand All @@ -227,13 +215,6 @@ export default {
},

methods: {
togglePassword() {
if (this.passwordInputType === 'password') {
this.passwordInputType = 'text'
} else {
this.passwordInputType = 'password'
}
},
updateUsername() {
this.$emit('update:username', this.user)
},
Expand All @@ -246,10 +227,15 @@ export default {
</script>

<style lang="scss" scoped>
.toggle-password {
position: absolute;
top: 2px;
right: 10px;
color: var(--color-text-lighter);
.login-form {
text-align: left;
font-size: 1rem;

&__fieldset {
width: 100%;
display: flex;
flex-direction: column;
gap: 1rem;
}
}
</style>
58 changes: 33 additions & 25 deletions core/src/components/login/ResetPassword.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,35 @@
-->

<template>
<form @submit.prevent="submit">
<fieldset>
<p>
<input id="user"
v-model="user"
type="text"
name="user"
autocapitalize="off"
:placeholder="t('core', 'Username or email')"
:aria-label="t('core', 'Username or email')"
required
@change="updateUsername">
<form @submit.prevent="submit" class="login-form">
<fieldset class="login-form__fieldset">
<NcTextField id="user"
:value.sync="user"
name="user"
autocapitalize="off"
:label="t('core', 'Username or email')"
:labelVisible="true"
required
@change="updateUsername" />
<!--<?php p($_['user_autofocus'] ? 'autofocus' : ''); ?>
autocomplete="<?php p($_['login_form_autocomplete']); ?>" autocapitalize="none" autocorrect="off"-->
<label for="user" class="infield">{{ t('core', 'Username or email') }}</label>
</p>
<div id="reset-password-wrapper">
<LoginButton :value="t('core', 'Reset password')" />
</div>
<p v-if="message === 'send-success'"
class="notecard success">
<NcNoteCard v-if="message === 'send-success'"
type="success">
{{ t('core', 'A password reset message has been sent to the email address of this account. If you do not receive it, check your spam/junk folders or ask your local administrator for help.') }}
<br>
{{ t('core', 'If it is not there ask your local administrator.') }}
</p>
<p v-else-if="message === 'send-error'"
class="notecard error">
</NcNoteCard>
<NcNoteCard v-else-if="message === 'send-error'"
type="error">
{{ t('core', 'Couldn\'t send reset email. Please contact your administrator.') }}
</p>
<p v-else-if="message === 'reset-error'"
class="notecard error">
</NcNoteCard>
<NcNoteCard v-else-if="message === 'reset-error'"
type="error">
{{ t('core', 'Password cannot be changed. Please contact your administrator.') }}
</p>
</NcNoteCard>

<a href="#"
@click.prevent="$emit('abort')">
Expand All @@ -66,11 +62,15 @@
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import LoginButton from './LoginButton.vue'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'

export default {
name: 'ResetPassword',
components: {
LoginButton,
NcNoteCard,
NcTextField,
},
props: {
username: {
Expand Down Expand Up @@ -131,7 +131,15 @@ export default {
</script>

<style scoped>
.update {
width: auto;
.login-form {
text-align: left;
font-size: 1rem;

&__fieldset {
width: 100%;
display: flex;
flex-direction: column;
gap: 1rem;
}
}
</style>
17 changes: 9 additions & 8 deletions core/src/views/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ export default {
</script>

<style lang="scss">
#login {
width: 300px;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .3s;
}
Expand All @@ -205,15 +208,13 @@ export default {
border-radius: var(--border-radius);
}

.alternative-logins button {
margin-top: 12px;
margin-bottom: 12px;
&:first-child {
margin-top: 0;
}
.alternative-logins {
display: flex;
flex-direction: column;
gap: 0.75rem;

&:last-child {
margin-bottom: 0;
.button-vue {
box-sizing: border-box;
}
}
</style>