- Move css in scopped vue components - Port to NcNoteCard all the warning messages Signed-off-by: Carl Schwan <carl@carlschwan.eu>tags/v25.0.0beta5
@@ -138,8 +138,7 @@ form #datadirField legend { | |||
} | |||
/* Buttons and input */ | |||
#submit-wrapper, | |||
#reset-password-wrapper { | |||
#submit-wrapper { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
@@ -155,8 +154,7 @@ form #datadirField legend { | |||
} | |||
#submit-wrapper .submit-icon, | |||
#reset-password-wrapper .submit-icon { | |||
#submit-wrapper .submit-icon { | |||
position: absolute; | |||
right: 24px; | |||
transition: right 100ms ease-in-out; | |||
@@ -176,12 +174,6 @@ form #datadirField legend { | |||
right: 20px; | |||
} | |||
#reset-password-submit { | |||
padding: 10px; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
} | |||
#submit-wrapper .icon-loading-small { | |||
position: absolute; | |||
top: 22px; | |||
@@ -457,25 +449,6 @@ form .warning input[type='checkbox']+label { | |||
#remember_login { | |||
margin: 18px 5px 0 16px !important; | |||
} | |||
.lost-password-container { | |||
display: inline-block; | |||
margin: 10px 0; | |||
text-align: center; | |||
width: 100%; | |||
} | |||
#lost-password, | |||
#lost-password-back, | |||
#reset-password-wrapper + a { | |||
display: inline-block; | |||
font-weight: normal !important; | |||
padding: 12px 12px 0 12px; | |||
cursor: pointer; | |||
} | |||
#forgot-password { | |||
padding: 11px; | |||
float: right; | |||
color: var(--color-primary-text); | |||
} | |||
/* 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 */ | |||
@@ -750,24 +723,22 @@ a.legal { | |||
} | |||
.notecard.success { | |||
--note-background: rgba(var(--color-success-rgb), 0.2); | |||
--note-background: rgba(var(--color-success-rgb), 0.1); | |||
--note-theme: var(--color-success); | |||
} | |||
.notecard.error { | |||
--note-background: rgba(var(--color-error-rgb), 0.2); | |||
--note-background: rgba(var(--color-error-rgb), 0.1); | |||
--note-theme: var(--color-error); | |||
} | |||
.notecard.warning { | |||
--note-background: rgba(var(--color-warning-rgb), 0.2); | |||
--note-background: rgba(var(--color-warning-rgb), 0.1); | |||
--note-theme: var(--color-warning); | |||
} | |||
.notecard { | |||
color: var(--color-text-light); | |||
background-color: var(--note-background); | |||
border: 1px solid var(--color-border); | |||
border-left: 4px solid var(--note-theme); | |||
border-radius: var(--border-radius); | |||
box-shadow: rgba(43, 42, 51, 0.05) 0px 1px 2px 0px; | |||
margin: 1rem 0; | |||
margin-top: 1rem; | |||
padding: 1rem; |
@@ -1,7 +0,0 @@ | |||
#reset-password p { | |||
position: relative; | |||
} | |||
.text-center { | |||
text-align: center; | |||
} |
@@ -62,3 +62,9 @@ export default { | |||
}, | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.button-vue { | |||
margin-top: .5rem; | |||
} | |||
</style> |
@@ -27,23 +27,22 @@ | |||
:action="loginActionUrl" | |||
@submit="submit"> | |||
<fieldset class="login-form__fieldset"> | |||
<div v-if="apacheAuthFailed" | |||
class="warning"> | |||
{{ t('core', 'Server side authentication failed!') }}<br> | |||
<small>{{ t('core', 'Please contact your administrator.') }} | |||
</small> | |||
</div> | |||
<div v-for="(message, index) in messages" | |||
:key="index" | |||
class="warning"> | |||
{{ message }}<br> | |||
</div> | |||
<div v-if="internalException" | |||
class="warning"> | |||
{{ t('core', 'An internal error occurred.') }}<br> | |||
<small>{{ t('core', 'Please try again or contact your administrator.') }} | |||
</small> | |||
</div> | |||
<NcNoteCard v-if="apacheAuthFailed" | |||
:title="t('core', 'Server side authentication failed!')" | |||
type="warning"> | |||
{{ t('core', 'Please contact your administrator.') }} | |||
</NcNoteCard> | |||
<NcNoteCard v-if="messages.length > 0"> | |||
<div v-for="(message, index) in messages" | |||
:key="index"> | |||
{{ message }}<br> | |||
</div> | |||
</NcNoteCard> | |||
<NcNoteCard v-if="internalException" | |||
:class="t('core', 'An internal error occurred.')" | |||
type="warning"> | |||
{{ t('core', 'Please try again or contact your administrator.') }} | |||
</NcNoteCard> | |||
<div id="message" | |||
class="hidden"> | |||
<img class="float-spinner" | |||
@@ -54,30 +53,29 @@ | |||
<div style="clear: both;" /> | |||
</div> | |||
<NcTextField id="user" | |||
:label="t('core', 'Username or email')" | |||
:labelVisible="true" | |||
ref="user" | |||
:label="t('core', 'Account name or email')" | |||
:label-visible="true" | |||
name="user" | |||
:class="{shake: invalidPassword}" | |||
:value.sync="user" | |||
:class="{shake: invalidPassword}" | |||
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" | |||
:label-visible="true" | |||
:class="{shake: invalidPassword}" | |||
:value.sync="password" | |||
:value="password" | |||
:spellchecking="false" | |||
autocapitalize="none" | |||
:autocomplete="autoCompleteAllowed ? 'current-password' : 'off'" | |||
:label="t('core', 'Password')" | |||
:helperText="errorLabel" | |||
:helper-text="errorLabel" | |||
:error="isError" | |||
required /> | |||
@@ -108,24 +106,20 @@ | |||
import jstz from 'jstimezonedetect' | |||
import { generateUrl, imagePath } from '@nextcloud/router' | |||
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' | |||
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js' | |||
import LoginButton from './LoginButton' | |||
import LoginButton from './LoginButton.vue' | |||
export default { | |||
name: 'LoginForm', | |||
components: { | |||
NcButton, | |||
Eye, | |||
EyeOff, | |||
LoginButton, | |||
NcPasswordField, | |||
NcTextField, | |||
NcNoteCard, | |||
}, | |||
props: { | |||
@@ -164,7 +158,7 @@ export default { | |||
loading: false, | |||
timezone: jstz.determine().name(), | |||
timezoneOffset: (-new Date().getTimezoneOffset() / 60), | |||
user: this.username, | |||
user: '', | |||
password: '', | |||
} | |||
}, | |||
@@ -184,7 +178,7 @@ export default { | |||
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; | |||
return undefined | |||
}, | |||
apacheAuthFailed() { | |||
return this.errors.indexOf('apacheAuthFailed') !== -1 | |||
@@ -210,6 +204,7 @@ export default { | |||
if (this.username === '') { | |||
this.$refs.user.focus() | |||
} else { | |||
this.user = this.username | |||
this.$refs.password.focus() | |||
} | |||
}, | |||
@@ -235,7 +230,7 @@ export default { | |||
width: 100%; | |||
display: flex; | |||
flex-direction: column; | |||
gap: 1rem; | |||
gap: .5rem; | |||
} | |||
} | |||
</style> |
@@ -20,21 +20,20 @@ | |||
--> | |||
<template> | |||
<form @submit.prevent="submit" class="login-form"> | |||
<form class="login-form" @submit.prevent="submit"> | |||
<fieldset class="login-form__fieldset"> | |||
<NcTextField id="user" | |||
:value.sync="user" | |||
name="user" | |||
autocapitalize="off" | |||
:label="t('core', 'Username or email')" | |||
:labelVisible="true" | |||
:label="t('core', 'Account name or email')" | |||
:label-visible="true" | |||
required | |||
@change="updateUsername" /> | |||
<!--<?php p($_['user_autofocus'] ? 'autofocus' : ''); ?> | |||
<!--<?php p($_['user_autofocus'] ? 'autofocus' : ''); ?> | |||
autocomplete="<?php p($_['login_form_autocomplete']); ?>" autocapitalize="none" autocorrect="off"--> | |||
<div id="reset-password-wrapper"> | |||
<LoginButton :value="t('core', 'Reset password')" /> | |||
</div> | |||
<LoginButton :value="t('core', 'Reset password')" /> | |||
<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.') }} | |||
@@ -50,7 +49,8 @@ | |||
{{ t('core', 'Password cannot be changed. Please contact your administrator.') }} | |||
</NcNoteCard> | |||
<a href="#" | |||
<a class="login-form__link" | |||
href="#" | |||
@click.prevent="$emit('abort')"> | |||
{{ t('core', 'Back to login') }} | |||
</a> | |||
@@ -130,7 +130,7 @@ export default { | |||
} | |||
</script> | |||
<style scoped> | |||
<style lang="scss" scoped> | |||
.login-form { | |||
text-align: left; | |||
font-size: 1rem; | |||
@@ -139,7 +139,17 @@ export default { | |||
width: 100%; | |||
display: flex; | |||
flex-direction: column; | |||
gap: 1rem; | |||
gap: .5rem; | |||
} | |||
&__link { | |||
display: block; | |||
font-weight: normal !important; | |||
padding-bottom: 1rem; | |||
cursor: pointer; | |||
font-size: var(--default-font-size); | |||
text-align: center; | |||
padding: .5rem 1rem 1rem 1rem; | |||
} | |||
} | |||
</style> |
@@ -20,7 +20,7 @@ | |||
--> | |||
<template> | |||
<div id="login" class="guest-box"> | |||
<div class="guest-box login-box"> | |||
<div v-if="!hideLoginForm || directLogin"> | |||
<transition name="fade" mode="out-in"> | |||
<div v-if="!passwordlessLogin && !resetPassword && resetPasswordTarget === ''"> | |||
@@ -34,16 +34,17 @@ | |||
@submit="loading = true" /> | |||
<a v-if="canResetPassword && resetPasswordLink !== ''" | |||
id="lost-password" | |||
class="login-box__link" | |||
:href="resetPasswordLink"> | |||
{{ t('core', 'Forgot password?') }} | |||
</a> | |||
<a v-else-if="canResetPassword && !resetPassword" | |||
id="lost-password" | |||
class="login-box__link" | |||
:href="resetPasswordLink" | |||
@click.prevent="resetPassword = true"> | |||
{{ t('core', 'Forgot password?') }} | |||
</a> | |||
<br> | |||
<template v-if="hasPasswordless"> | |||
<div v-if="countAlternativeLogins" | |||
class="alternative-logins"> | |||
@@ -72,7 +73,7 @@ | |||
:is-localhost="isLocalhost" | |||
:has-public-key-credential="hasPublicKeyCredential" | |||
@submit="loading = true" /> | |||
<a href="#" @click.prevent="passwordlessLogin = false"> | |||
<a href="#" class="login-box__link" @click.prevent="passwordlessLogin = false"> | |||
{{ t('core', 'Back') }} | |||
</a> | |||
</div> | |||
@@ -95,19 +96,16 @@ | |||
</div> | |||
<div v-else> | |||
<transition name="fade" mode="out-in"> | |||
<div class="warning"> | |||
{{ t('core', 'Login form is disabled.') }}<br> | |||
<small> | |||
{{ t('core', 'Please contact your administrator.') }} | |||
</small> | |||
</div> | |||
<NcNoteCard type="warning" :title="t('core', 'Login form is disabled.')"> | |||
{{ t('core', 'Please contact your administrator.') }} | |||
</NcNoteCard> | |||
</transition> | |||
</div> | |||
<div id="alternative-logins" class="alternative-logins"> | |||
<NcButton v-for="(alternativeLogin, index) in alternativeLogins" | |||
:key="index" | |||
type="primary" | |||
type="secondary" | |||
:wide="true" | |||
:class="[alternativeLogin.class]" | |||
role="link" | |||
@@ -127,7 +125,8 @@ import LoginForm from '../components/login/LoginForm.vue' | |||
import PasswordLessLoginForm from '../components/login/PasswordLessLoginForm.vue' | |||
import ResetPassword from '../components/login/ResetPassword.vue' | |||
import UpdatePassword from '../components/login/UpdatePassword.vue' | |||
import NcButton from '@nextcloud/vue/dist/Components/NcButton' | |||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' | |||
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js' | |||
const query = queryString.parse(location.search) | |||
if (query.clear === '1') { | |||
@@ -149,6 +148,7 @@ export default { | |||
ResetPassword, | |||
UpdatePassword, | |||
NcButton, | |||
NcNoteCard, | |||
}, | |||
data() { | |||
@@ -192,29 +192,35 @@ export default { | |||
</script> | |||
<style lang="scss"> | |||
#login { | |||
width: 300px; | |||
} | |||
.fade-enter-active, .fade-leave-active { | |||
transition: opacity .3s; | |||
} | |||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { | |||
opacity: 0; | |||
} | |||
body { | |||
font-size: var(--default-font-size); | |||
} | |||
.login-box { | |||
width: 300px; | |||
#lost-password { | |||
padding: 4px; | |||
margin: 8px; | |||
border-radius: var(--border-radius); | |||
&__link { | |||
display: block; | |||
padding: 1rem; | |||
font-size: var(--default-font-size); | |||
text-align: center; | |||
font-weight: normal !important; | |||
} | |||
} | |||
.fade-enter-active, .fade-leave-active { | |||
transition: opacity .3s; | |||
} | |||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { | |||
opacity: 0; | |||
} | |||
.alternative-logins { | |||
display: flex; | |||
flex-direction: column; | |||
gap: 0.75rem; | |||
.alternative-logins { | |||
display: flex; | |||
flex-direction: column; | |||
gap: 0.75rem; | |||
.button-vue { | |||
box-sizing: border-box; | |||
} | |||
.button-vue { | |||
box-sizing: border-box; | |||
} | |||
} | |||
</style> |
@@ -392,6 +392,8 @@ | |||
/*! For license information please see NcRichContenteditable.js.LICENSE.txt */ | |||
/*! For license information please see NcTextField.js.LICENSE.txt */ | |||
/*! For license information please see NcTimezonePicker.js.LICENSE.txt */ | |||
/*! For license information please see Tooltip.js.LICENSE.txt */ |
@@ -54,7 +54,7 @@ class LoginPageContext implements Context, ActorAwareInterface { | |||
} | |||
public static function wrongPasswordMessage(): Locator { | |||
return Locator::forThe()->xpath("//*[@class = 'warning wrongPasswordMsg' and normalize-space() = 'Wrong username or password.']")-> | |||
return Locator::forThe()->xpath("//*[@class = 'input-field__helper-text-message input-field__helper-text-message--error' and normalize-space() = 'Wrong username or password.']")-> | |||
describedAs("Wrong password message in Login page"); | |||
} | |||
@@ -62,7 +62,7 @@ class LoginPageContext implements Context, ActorAwareInterface { | |||
* @return Locator | |||
*/ | |||
public static function userDisabledMessage() { | |||
return Locator::forThe()->xpath("//*[@class = 'warning userDisabledMsg' and normalize-space() = 'User disabled']")-> | |||
return Locator::forThe()->xpath("//*[@class = 'input-field__helper-text-message input-field__helper-text-message--error' and normalize-space() = 'User disabled']")-> | |||
describedAs('User disabled message on login page'); | |||
} | |||