@ -1,20 +1,41 @@
< template lang = "pug" >
v - app
. login
. login - container ( : class = '{ "is-expanded": strategies.length > 1, "is-loading": isLoading }' )
. login - mascot
img ( src = '/svg/henry-reading.svg' , alt = 'Henry' )
. login - providers ( v - show = 'strategies.length > 1' )
button ( v - for = 'strategy in strategies' , : class = '{ "is-active": strategy.key === selectedStrategy }' , @ click = 'selectStrategy(strategy.key, strategy.useForm)' , : title = 'strategy.title' )
em ( v - html = 'strategy.icon' )
span { { strategy . title } }
. login - providers - fill
. login - frame ( v - show = 'screen === "login"' )
h1 . text - xs - center . display - 1 { { siteTitle } }
h2 . text - xs - center . subheading { { $t ( 'auth:loginRequired' ) } }
v - text - field ( solo , hide - details , ref = 'iptEmail' , v - model = 'username' , : placeholder = '$t("auth:fields.emailUser")' )
v - text - field . mt - 2 (
v - container ( grid - list - lg )
v - layout ( row , wrap )
v - flex (
xs12
offset - sm1 , sm10
offset - md2 , md8
offset - lg3 , lg6
offset - xl4 , xl4
)
transition ( name = 'zoom' )
v - card . elevation - 5. radius - 7 ( v - show = 'isShown' )
v - toolbar ( color = 'primary' , flat , dense , dark )
v - spacer
. subheading ( v - if = 'screen === "tfa"' ) { { $t ( 'auth:tfa.subtitle' ) } }
. subheading ( v - else - if = 'selectedStrategy.key !== "local"' ) Login using { { selectedStrategy . title } }
. subheading ( v - else ) { { $t ( 'auth:loginRequired' ) } }
v - spacer
v - card - text . text - xs - center
h1 . display - 1. primary -- text . py - 2 { { siteTitle } }
template ( v - if = 'screen === "login"' )
v - text - field . md2 . mt - 3 (
solo
flat
prepend - icon = 'email'
background - color = 'grey lighten-4'
hide - details
ref = 'iptEmail'
v - model = 'username'
: placeholder = '$t("auth:fields.emailUser")'
)
v - text - field . md2 . mt - 2 (
solo
flat
prepend - icon = 'vpn_key'
background - color = 'grey lighten-4'
hide - details
ref = 'iptPassword'
v - model = 'password'
@ -24,24 +45,70 @@
: placeholder = '$t("auth:fields.password")'
@ keyup . enter = 'login'
)
v - btn . mt - 3 ( block , large , color = 'primary' , @ click = 'login' ) { { $t ( 'auth:actions.login' ) } }
. login - frame ( v - show = 'screen === "tfa"' )
. login - frame - icon
svg . icons . is - 48 ( role = 'img' )
title { { $t ( 'auth:tfa.title' ) } }
use ( xlink : href = '#nc-key' )
h2 { { $t ( 'auth:tfa.subtitle' ) } }
input ( type = 'text' , ref = 'iptTFA' , v - model = 'securityCode' , : placeholder = '$t("auth:tfa.placeholder")' , @ keyup . enter = 'verifySecurityCode' )
button . button . is - blue . is - fullwidth ( @ click = 'verifySecurityCode' )
span { { $t ( 'auth:tfa.verifyToken' ) } }
nav - footer ( altbg )
template ( v - if = 'screen === "tfa"' )
. body - 2 Enter the security code generated from your trusted device :
v - text - field . md2 . centered . mt - 2 (
solo
flat
background - color = 'grey lighten-4'
hide - details
ref = 'iptTFA'
v - model = 'securityCode'
: placeholder = '$t("auth:tfa.placeholder")'
@ keyup . enter = 'verifySecurityCode'
)
v - card - actions . pb - 4
v - spacer
v - btn (
v - if = 'screen === "login"'
block
large
color = 'primary'
@ click = 'login'
round
: loading = 'isLoading'
) { { $t ( 'auth:actions.login' ) } }
v - btn (
v - if = 'screen === "tfa"'
block
large
color = 'primary'
@ click = 'verifySecurityCode'
round
: loading = 'isLoading'
) { { $t ( 'auth:tfa.verifyToken' ) } }
v - spacer
v - card - actions . pb - 3 ( v - if = 'selectedStrategy.key === "local"' )
v - spacer
a . caption ( href = '' ) Forgot your password ?
v - spacer
template ( v - if = 'isSocialShown' )
v - divider
v - card - text . grey . lighten - 4. text - xs - center
. pb - 2. body - 2. text - xs - center . grey -- text . text -- darken - 2 or login using ...
v - tooltip ( top , v - for = 'strategy in strategies' , : key = 'strategy.key' )
. social - login - btn . mr - 2 (
slot = 'activator'
v - ripple
v - html = 'strategy.icon'
: class = 'strategy.color + " elevation-" + (strategy.key === selectedStrategy.key ? "0" : "4")'
@ click = 'selectStrategy(strategy)'
)
span { { strategy . title } }
template ( v - if = 'selectedStrategy.selfRegistration' )
v - divider
v - card - actions . py - 3 ( : class = 'isSocialShown ? "" : "grey lighten-4"' )
v - spacer
. caption Don 't have an account yet? #[a.caption(href=' ' ) Create an account ]
v - spacer
nav - footer ( color = 'grey darken-4' )
< / template >
< script >
/* global siteConfig */
import _ from 'lodash'
import { mapState } from 'vuex'
import Cookies from 'js-cookie '
import strategiesQuery from 'gql/login/login-query-strategies.gql'
import loginMutation from 'gql/login/login-mutation-login.gql'
@ -53,41 +120,50 @@ export default {
return {
error : false ,
strategies : [ ] ,
selectedStrategy : 'local' ,
selectedStrategy : { key : 'local' } ,
screen : 'login' ,
username : '' ,
password : '' ,
hidePassword : true ,
securityCode : '' ,
loginToken : '' ,
isLoading : false
isLoading : false ,
isShown : false
}
} ,
computed : {
... mapState ( [ 'notification' ] ) ,
notificationState : {
get ( ) { return this . notification . isActive } ,
set ( newState ) { this . $store . commit ( 'updateNotificationState' , newState ) }
} ,
siteTitle ( ) {
return siteConfig . title
} ,
isSocialShown ( ) {
return this . strategies . length > 1
}
} ,
watch : {
strategies ( newValue , oldValue ) {
this . selectedStrategy = _ . find ( newValue , [ 'key' , 'local' ] )
}
} ,
mounted ( ) {
this . isShown = true
this . $nextTick ( ( ) => {
this . $refs . iptEmail . focus ( )
} )
} ,
methods : {
/ * *
* SELECT STRATEGY
* /
selectStrategy ( key, useForm ) {
this . selectedStrategy = ke y
selectStrategy ( strategy ) {
this . selectedStrategy = strateg y
this . screen = 'login'
if ( ! useForm) {
if ( ! strategy. useForm) {
this . isLoading = true
window . location . assign ( this . $helpers . resolvePath ( 'login/' + key) )
window . location . assign ( this . $helpers . resolvePath ( 'login/' + strategy. key) )
} else {
this . $nextTick ( ( ) => {
this . $refs . iptEmail . focus ( )
} )
}
} ,
/ * *
@ -116,7 +192,7 @@ export default {
variables : {
username : this . username ,
password : this . password ,
strategy : this . selectedStrategy
strategy : this . selectedStrategy . key
}
} )
if ( _ . has ( resp , 'data.authentication.login' ) ) {
@ -135,6 +211,7 @@ export default {
style : 'success' ,
icon : 'check'
} )
Cookies . set ( 'jwt' , respObj . jwt , { expires : 365 } )
_ . delay ( ( ) => {
window . location . replace ( '/' ) / / T E M P O R A R Y - U S E R E T U R N U R L
} , 1000 )
@ -222,15 +299,12 @@ export default {
< style lang = "scss" >
. login {
background - color : mc ( ' blue', '8 00') ;
background - color : mc ( ' grey', '9 00') ;
background - image : url ( '../static/svg/motif-blocks.svg' ) ;
background - repeat : repeat ;
background - size : 200 px ;
width : 100 % ;
height : 100 % ;
display : flex ;
align - items : center ;
justify - content : center ;
animation : loginBgReveal 20 s linear infinite ;
@ include keyframes ( loginBgReveal ) {
@ -245,7 +319,6 @@ export default {
& : : before {
content : '' ;
position : absolute ;
background - color : # 0 d47a1 ;
background - image : url ( '../static/svg/motif-overlay.svg' ) ;
background - attachment : fixed ;
background - size : cover ;
@ -256,259 +329,41 @@ export default {
height : 100 vh ;
}
& : : after {
content : '' ;
position : absolute ;
background - image : linear - gradient ( to bottom , rgba ( mc ( 'blue' , '800' ) , .9 ) 0 % , rgba ( mc ( 'blue' , '800' ) , 0 ) 100 % ) ;
top : 0 ;
left : 0 ;
width : 100 vw ;
height : 25 vh ;
z - index : 1 ;
}
& - mascot {
width : 200 px ;
height : 200 px ;
position : absolute ;
top : - 180 px ;
left : 50 % ;
margin - left : - 100 px ;
z - index : 10 ;
@ include until ( $tablet ) {
display : none ;
}
}
& - container {
position : relative ;
display : flex ;
width : 400 px ;
align - items : stretch ;
box - shadow : 0 14 px 28 px rgba ( 0 , 0 , 0 , 0.2 ) ;
border - radius : 6 px ;
animation : zoomIn .5 s ease ;
z - index : 2 ;
& : : after {
position : absolute ;
top : 1 rem ;
right : 1 rem ;
content : " " ;
@ include spinner ( mc ( 'blue' , '500' ) , 0.5 s , 16 px ) ;
display : none ;
}
& . is - expanded {
width : 650 px ;
. login - frame {
border - radius : 0 6 px 6 px 0 ;
border - left : none ;
@ include until ( $tablet ) {
border - radius : 0 ;
}
}
}
& . is - loading : : after {
display : block ;
}
@ include until ( $tablet ) {
width : 95 vw ;
border - radius : 0 ;
& . is - expanded {
width : 95 vw ;
}
}
}
& - providers {
> . container {
height : 100 % ;
align - items : center ;
display : flex ;
flex - direction : column ;
width : 250 px ;
border - right : none ;
border - radius : 6 px 0 0 6 px ;
z - index : 1 ;
overflow : hidden ;
@ include until ( $tablet ) {
width : 50 px ;
border - radius : 0 ;
}
button {
flex : 0 1 50 px ;
padding : 5 px 15 px ;
border : none ;
color : # FFF ;
/ / b a c k g r o u n d : l i n e a r - g r a d i e n t ( t o r i g h t , r g b a ( m c ( ' l i g h t - b l u e ' , ' 8 0 0 ' ) , . 7 ) , r g b a ( m c ( ' l i g h t - b l u e ' , ' 8 0 0 ' ) , 1 ) ) ;
/ / b o r d e r - t o p : 1 p x s o l i d r g b a ( m c ( ' l i g h t - b l u e ' , ' 9 0 0 ' ) , . 5 ) ;
background : linear - gradient ( to right , rgba ( 0 , 0 , 0 , .5 ) , rgba ( 0 , 0 , 0 , .7 ) ) ;
border - top : 1 px solid rgba ( 0 , 0 , 0 , .2 ) ;
font - weight : 600 ;
text - align : left ;
min - height : 40 px ;
display : flex ;
justify - content : flex - start ;
align - items : center ;
transition : all .4 s ease ;
& : focus {
outline : none ;
h1 {
font - family : 'Varela Round' ! important ;
}
@ include until ( $tablet ) {
. social - login - btn {
display : inline - flex ;
justify - content : center ;
}
& : hover {
background - color : rgba ( 0 , 0 , 0 , .4 ) ;
}
& : first - child {
border - top : none ;
& . is - active {
border - top : 1 px solid rgba ( 255 , 255 , 255 , .5 ) ;
}
}
& . is - active {
background - image : linear - gradient ( to right , rgba ( 255 , 255 , 255 , 1 ) 0 % , rgba ( 255 , 255 , 255 , .77 ) 100 % ) ;
color : mc ( 'grey' , '800' ) ;
cursor : default ;
align - items : center ;
border - radius : 50 % ;
width : 54 px ;
height : 54 px ;
cursor : pointer ;
transition : opacity .2 s ease ;
& : hover {
background - color : transparent ;
}
svg path {
fill : mc ( 'grey' , '800' ) ;
}
opacity : .8 ;
}
i {
margin - right : 10 px ;
font - size : 16 px ;
@ include until ( $tablet ) {
margin - right : 0 ;
font - size : 20 px ;
}
}
margin : .5 rem 0 ;
svg {
margin - right : 10 px ;
width : auto ;
height : 20 px ;
max - width : 18 px ;
max - height : 20 px ;
width : 24 px ;
height : 24 px ;
bottom : 0 ;
path {
fill : # FFF ;
}
@ include until ( $tablet ) {
margin - right : 0 ;
font - size : 20 px ;
}
}
em {
height : 20 px ;
}
span {
font - weight : 600 ;
@ include until ( $tablet ) {
display : none ;
}
}
}
& - fill {
flex : 1 1 0 ;
background : linear - gradient ( to right , rgba ( mc ( 'light-blue' , '800' ) , .7 ) , rgba ( mc ( 'light-blue' , '800' ) , 1 ) ) ;
}
}
& - frame {
background - image : radial - gradient ( circle at top center , rgba ( 255 , 255 , 255 , 1 ) 5 % , rgba ( 255 , 255 , 255 , .6 ) 100 % ) ;
border : 1 px solid rgba ( 255 , 255 , 255 , .5 ) ;
border - radius : 6 px ;
width : 400 px ;
padding : 1 rem ;
color : mc ( 'grey' , '700' ) ;
display : block ;
@ include until ( $tablet ) {
width : 100 % ;
border - radius : 0 ;
border : none ;
}
h1 {
font - size : 2 rem ;
font - weight : 400 ;
color : mc ( 'light-blue' , '700' ) ;
text - shadow : 1 px 1 px 0 # FFF ;
padding : 1 rem 0 0 0 ;
margin : 0 ;
}
h2 {
font - size : 1.5 rem ;
font - weight : 300 ;
color : mc ( 'grey' , '700' ) ;
text - shadow : 1 px 1 px 0 # FFF ;
padding : 0 ;
margin : 0 0 25 px 0 ;
}
}
& - tfa {
position : relative ;
display : flex ;
width : 400 px ;
align - items : stretch ;
box - shadow : 0 14 px 28 px rgba ( 0 , 0 , 0 , 0.2 ) ;
border - radius : 6 px ;
animation : zoomIn .5 s ease ;
}
& - copyright {
display : flex ;
align - items : center ;
justify - content : center ;
position : absolute ;
left : 0 ;
bottom : 10 vh ;
width : 100 % ;
z - index : 2 ;
color : mc ( 'grey' , '500' ) ;
font - weight : 400 ;
a {
font - weight : 600 ;
color : mc ( 'blue' , '500' ) ;
margin - left : .25 rem ;
@ include until ( $tablet ) {
color : mc ( 'blue' , '200' ) ;
}
}
@ include until ( $tablet ) {
color : mc ( 'blue' , '50' ) ;
}
. v - text - field . centered input {
text - align : center ;
}
}
< / style >