-import { Options, passwordStrength } from "check-password-strength";
-import { NoOptionI18nKeys } from "i18next";
+import { myAuth, setIsoData } from "@utils/app";
+import { isBrowser } from "@utils/browser";
+import { validEmail } from "@utils/helpers";
import { Component, linkEvent } from "inferno";
import { T } from "inferno-i18next-dess";
import {
LoginResponse,
SiteView,
} from "lemmy-js-client";
-import { i18n } from "../../i18next";
-import { UserService } from "../../services";
+import { joinLemmyUrl } from "../../config";
+import { mdToHtml } from "../../markdown";
+import { I18NextService, UserService } from "../../services";
import { HttpService, RequestState } from "../../services/HttpService";
-import {
- joinLemmyUrl,
- mdToHtml,
- myAuth,
- setIsoData,
- toast,
- validEmail,
-} from "../../utils";
-import isBrowser from "../../utils/browser/is-browser";
+import { toast } from "../../toast";
import { HtmlTags } from "../common/html-tags";
import { Icon, Spinner } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea";
-
-const passwordStrengthOptions: Options<string> = [
- {
- id: 0,
- value: "very_weak",
- minDiversity: 0,
- minLength: 0,
- },
- {
- id: 1,
- value: "weak",
- minDiversity: 2,
- minLength: 10,
- },
- {
- id: 2,
- value: "medium",
- minDiversity: 3,
- minLength: 12,
- },
- {
- id: 3,
- value: "strong",
- minDiversity: 4,
- minLength: 14,
- },
-];
+import PasswordInput from "../common/password-input";
interface State {
registerRes: RequestState<LoginResponse>;
}
titleName(siteView: SiteView): string {
- return i18n.t(
+ return I18NextService.i18n.t(
siteView.local_site.private_instance ? "apply_to_join" : "sign_up"
);
}
render() {
return (
- <div className="container-lg">
+ <div className="home-signup container-lg">
<HtmlTags
title={this.documentTitle}
path={this.context.router.route.match.url}
registerForm() {
const siteView = this.state.siteRes.site_view;
return (
- <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
- <h5>{this.titleName(siteView)}</h5>
+ <form
+ className="was-validated"
+ onSubmit={linkEvent(this, this.handleRegisterSubmit)}
+ >
+ <h1 className="h4 mb-4">{this.titleName(siteView)}</h1>
{this.isLemmyMl && (
- <div className="form-group row">
+ <div className="mb-3 row">
<div className="mt-2 mb-0 alert alert-warning" role="alert">
<T i18nKey="lemmy_ml_registration_message">
#<a href={joinLemmyUrl}>#</a>
</div>
)}
- <div className="form-group row">
+ <div className="mb-3 row">
<label
className="col-sm-2 col-form-label"
htmlFor="register-username"
>
- {i18n.t("username")}
+ {I18NextService.i18n.t("username")}
</label>
<div className="col-sm-10">
required
minLength={3}
pattern="[a-zA-Z0-9_]+"
- title={i18n.t("community_reqs")}
+ title={I18NextService.i18n.t("community_reqs")}
/>
</div>
</div>
- <div className="form-group row">
+ <div className="mb-3 row">
<label className="col-sm-2 col-form-label" htmlFor="register-email">
- {i18n.t("email")}
+ {I18NextService.i18n.t("email")}
</label>
<div className="col-sm-10">
<input
className="form-control"
placeholder={
siteView.local_site.require_email_verification
- ? i18n.t("required")
- : i18n.t("optional")
+ ? I18NextService.i18n.t("required")
+ : I18NextService.i18n.t("optional")
}
value={this.state.form.email}
autoComplete="email"
this.state.form.email &&
!validEmail(this.state.form.email) && (
<div className="mt-2 mb-0 alert alert-warning" role="alert">
- <Icon icon="alert-triangle" classes="icon-inline mr-2" />
- {i18n.t("no_password_reset")}
+ <Icon icon="alert-triangle" classes="icon-inline me-2" />
+ {I18NextService.i18n.t("no_password_reset")}
</div>
)}
</div>
</div>
- <div className="form-group row">
- <label
- className="col-sm-2 col-form-label"
- htmlFor="register-password"
- >
- {i18n.t("password")}
- </label>
- <div className="col-sm-10">
- <input
- type="password"
- id="register-password"
- value={this.state.form.password}
- autoComplete="new-password"
- onInput={linkEvent(this, this.handleRegisterPasswordChange)}
- minLength={10}
- maxLength={60}
- className="form-control"
- required
- />
- {this.state.form.password && (
- <div className={this.passwordColorClass}>
- {i18n.t(this.passwordStrength as NoOptionI18nKeys)}
- </div>
- )}
- </div>
+ <div className="mb-3">
+ <PasswordInput
+ id="register-password"
+ value={this.state.form.password}
+ onInput={linkEvent(this, this.handleRegisterPasswordChange)}
+ showStrength
+ label={I18NextService.i18n.t("password")}
+ />
</div>
- <div className="form-group row">
- <label
- className="col-sm-2 col-form-label"
- htmlFor="register-verify-password"
- >
- {i18n.t("verify_password")}
- </label>
- <div className="col-sm-10">
- <input
- type="password"
- id="register-verify-password"
- value={this.state.form.password_verify}
- autoComplete="new-password"
- onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
- maxLength={60}
- className="form-control"
- required
- />
- </div>
+ <div className="mb-3">
+ <PasswordInput
+ id="register-verify-password"
+ value={this.state.form.password_verify}
+ onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
+ label={I18NextService.i18n.t("verify_password")}
+ />
</div>
- {siteView.local_site.registration_mode == "RequireApplication" && (
+ {siteView.local_site.registration_mode === "RequireApplication" && (
<>
- <div className="form-group row">
+ <div className="mb-3 row">
<div className="offset-sm-2 col-sm-10">
<div className="mt-2 alert alert-warning" role="alert">
- <Icon icon="alert-triangle" classes="icon-inline mr-2" />
- {i18n.t("fill_out_application")}
+ <Icon icon="alert-triangle" classes="icon-inline me-2" />
+ {I18NextService.i18n.t("fill_out_application")}
</div>
{siteView.local_site.application_question && (
<div
</div>
</div>
- <div className="form-group row">
+ <div className="mb-3 row">
<label
className="col-sm-2 col-form-label"
htmlFor="application_answer"
>
- {i18n.t("answer")}
+ {I18NextService.i18n.t("answer")}
</label>
<div className="col-sm-10">
<MarkdownTextArea
</>
)}
{this.renderCaptcha()}
- <div className="form-group row">
+ <div className="mb-3 row">
<div className="col-sm-10">
<div className="form-check">
<input
onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
/>
<label className="form-check-label" htmlFor="register-show-nsfw">
- {i18n.t("show_nsfw")}
+ {I18NextService.i18n.t("show_nsfw")}
</label>
</div>
</div>
value={this.state.form.honeypot}
onInput={linkEvent(this, this.handleHoneyPotChange)}
/>
- <div className="form-group row">
+ <div className="mb-3 row">
<div className="col-sm-10">
<button type="submit" className="btn btn-secondary">
{this.state.registerRes.state == "loading" ? (
case "success": {
const res = this.state.captchaRes.data;
return (
- <div className="form-group row">
+ <div className="mb-3 row">
<label className="col-sm-2" htmlFor="register-captcha">
- <span className="mr-2">{i18n.t("enter_code")}</span>
+ <span className="me-2">
+ {I18NextService.i18n.t("enter_code")}
+ </span>
<button
type="button"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleRegenCaptcha)}
- aria-label={i18n.t("captcha")}
+ aria-label={I18NextService.i18n.t("captcha")}
>
<Icon icon="refresh-cw" classes="icon-refresh-cw" />
</button>
className="rounded-top img-fluid"
src={this.captchaPngSrc(captchaRes)}
style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;"
- alt={i18n.t("captcha")}
+ alt={I18NextService.i18n.t("captcha")}
/>
{captchaRes.wav && (
<button
- className="rounded-bottom btn btn-sm btn-secondary btn-block"
+ className="rounded-bottom btn btn-sm btn-secondary d-block"
style="border-top-right-radius: 0; border-top-left-radius: 0;"
- title={i18n.t("play_captcha_audio")}
+ title={I18NextService.i18n.t("play_captcha_audio")}
onClick={linkEvent(this, this.handleCaptchaPlay)}
type="button"
disabled={this.state.captchaPlaying}
);
}
- get passwordStrength(): string | undefined {
- const password = this.state.form.password;
- return password
- ? passwordStrength(password, passwordStrengthOptions).value
- : undefined;
- }
-
- get passwordColorClass(): string {
- const strength = this.passwordStrength;
-
- if (strength && ["weak", "medium"].includes(strength)) {
- return "text-warning";
- } else if (strength == "strong") {
- return "text-success";
- } else {
- return "text-danger";
- }
- }
-
async handleRegisterSubmit(i: Signup, event: any) {
event.preventDefault();
const {
// Only log them in if a jwt was set
if (data.jwt) {
- UserService.Instance.login(data);
+ UserService.Instance.login({
+ res: data,
+ });
const site = await HttpService.client.getSite({ auth: myAuth() });
i.props.history.replace("/communities");
} else {
if (data.verify_email_sent) {
- toast(i18n.t("verify_email_sent"));
+ toast(I18NextService.i18n.t("verify_email_sent"));
}
if (data.registration_created) {
- toast(i18n.t("registration_application_sent"));
+ toast(I18NextService.i18n.t("registration_application_sent"));
}
i.props.history.push("/");
}