package login
import (
"fmt"
"net/http"
v "github.com/qor5/ui/vuetify"
"github.com/qor5/web"
"github.com/qor5/x/login"
. "github.com/theplant/htmlgo"
)
var DefaultViewCommon = &ViewCommon{
WrapperClass: "d-flex pt-16 flex-column mx-auto",
WrapperStyle: "max-width: 28rem;",
TitleClass: "text-h5 mb-6 font-weight-bold",
LabelClass: "d-block mb-1 grey--text text--darken-2 text-sm-body-2",
}
type ViewCommon struct {
WrapperClass string
WrapperStyle string
TitleClass string
LabelClass string
}
func (vc *ViewCommon) Notice(vh *login.ViewHelper, msgr *login.Messages, w http.ResponseWriter, r *http.Request) HTMLComponent {
var nn HTMLComponent
if n := vh.GetNoticeFlash(w, r); n != nil && n.Message != "" {
switch n.Level {
case login.NoticeLevel_Info:
nn = vc.InfoNotice(n.Message)
case login.NoticeLevel_Warn:
nn = vc.WarnNotice(n.Message)
case login.NoticeLevel_Error:
nn = vc.ErrNotice(n.Message)
}
}
return Components(
vc.ErrNotice(vh.GetFailFlashMessage(msgr, w, r)),
vc.WarnNotice(vh.GetWarnFlashMessage(msgr, w, r)),
vc.InfoNotice(vh.GetInfoFlashMessage(msgr, w, r)),
nn,
)
}
func (vc *ViewCommon) ErrNotice(msg string) HTMLComponent {
if msg == "" {
return nil
}
return v.VAlert(Text(msg)).
Dense(true).
Class("text-center").
Icon(false).
Type("error")
}
func (vc *ViewCommon) WarnNotice(msg string) HTMLComponent {
if msg == "" {
return nil
}
return v.VAlert(Text(msg)).
Dense(true).
Class("text-center").
Icon(false).
Type("warning")
}
func (vc *ViewCommon) InfoNotice(msg string) HTMLComponent {
if msg == "" {
return nil
}
return v.VAlert(Text(msg)).
Dense(true).
Class("text-center").
Icon(false).
Type("info")
}
func (vc *ViewCommon) ErrorBody(msg string) HTMLComponent {
return Div(
Text(msg),
)
}
func (vc *ViewCommon) Input(
id string,
placeholder string,
val string,
) *v.VTextFieldBuilder {
return v.VTextField().
Attr("name", id).
Id(id).
Placeholder(placeholder).
Value(val).
Outlined(true).
HideDetails(true).
Dense(true)
}
func (vc *ViewCommon) PasswordInput(
id string,
placeholder string,
val string,
canReveal bool,
) *v.VTextFieldBuilder {
in := vc.Input(id, placeholder, val)
if canReveal {
varName := fmt.Sprintf(`show_%s`, id)
in.Attr(":append-icon", fmt.Sprintf(`vars.%s ? "visibility_off" : "visibility"`, varName)).
Attr(":type", fmt.Sprintf(`vars.%s ? "text" : "password"`, varName)).
Attr("@click:append", fmt.Sprintf(`vars.%s = !vars.%s`, varName, varName)).
Attr(web.InitContextVars, fmt.Sprintf(`{%s: false}`, varName))
}
return in
}
// need to import zxcvbn js
// func (vc *ViewCommon) PasswordInputWithStrengthMeter(in *v.VTextFieldBuilder, id string, val string) HTMLComponent {
// passVar := fmt.Sprintf(`password_%s`, id)
// meterScoreVar := fmt.Sprintf(`meter_score_%s`, id)
// in.Attr("v-model", fmt.Sprintf(`vars.%s`, passVar)).
// Attr(":loading", fmt.Sprintf(`!!vars.%s`, passVar)).
// On("input", fmt.Sprintf(`vars.%s = vars.%s ? zxcvbn(vars.%s).score + 1 : 0`, meterScoreVar, passVar, passVar))
// return Div(
// in.Children(
// RawHTML(fmt.Sprintf(`
//
//
//
// `, meterScoreVar, meterScoreVar)),
// ),
// ).Attr(web.InitContextVars, fmt.Sprintf(`{%s: "%s", %s: "%s" ? zxcvbn("%s").score + 1 : 0}`, passVar, val, meterScoreVar, val, val))
// }
// need to import zxcvbn.js
func (vc *ViewCommon) PasswordInputWithStrengthMeter(in *v.VTextFieldBuilder, id string, val string) HTMLComponent {
passVar := fmt.Sprintf(`password_%s`, id)
meterScoreVar := fmt.Sprintf(`meter_score_%s`, id)
in.Attr("v-model", fmt.Sprintf(`vars.%s`, passVar)).
On("input", fmt.Sprintf(`vars.%s = vars.%s ? zxcvbn(vars.%s).score + 1 : 0`, meterScoreVar, passVar, passVar))
return Div(
in,
v.VProgressLinear().
Class("mt-2").
Attr(":value", fmt.Sprintf(`vars.%s * 20`, meterScoreVar)).
Attr(":color", fmt.Sprintf(`["grey", "red", "deep-orange", "amber", "yellow", "light-green"][vars.%s]`, meterScoreVar)).
Attr("v-show", fmt.Sprintf(`!!vars.%s`, passVar)),
).Attr(web.InitContextVars, fmt.Sprintf(`{%s: "%s", %s: "%s" ? zxcvbn("%s").score + 1 : 0}`, passVar, val, meterScoreVar, val, val))
}
func (vc *ViewCommon) FormSubmitBtn(
label string,
) *v.VBtnBuilder {
return v.VBtn(label).
Color("primary").
Block(true).
Large(true).
Type("submit").
Class("mt-6")
}
// requirements:
// - submit button
// - add class `g-recaptcha`
// - add attr `data-sitekey=`
// - add attr `data-callback=onSubmit`
//
// - add token field like `Input("token").Id("token").Type("hidden")`
func (vc *ViewCommon) InjectRecaptchaAssets(ctx *web.EventContext, formID string, tokenFieldID string) {
ctx.Injector.HeadHTML(`
`)
ctx.Injector.HeadHTML(fmt.Sprintf(`
`, tokenFieldID, formID))
ctx.Injector.TailHTML(`
`)
}
func (vc *ViewCommon) InjectZxcvbn(ctx *web.EventContext) {
ctx.Injector.HeadHTML(fmt.Sprintf(`
`, login.ZxcvbnJSURL))
}