Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/src/packages/frontend/app/verify-email-banner.tsx
Views: 821
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Space } from "antd";6import { FormattedMessage, useIntl } from "react-intl";78import { emailVerificationMsg } from "@cocalc/frontend/account/settings/email-verification";9import { Button } from "@cocalc/frontend/antd-bootstrap";10import {11CSS,12redux,13useActions,14useAsyncEffect,15useState,16useTypedRedux,17} from "@cocalc/frontend/app-framework";18import { CloseX2, HelpIcon, Icon, Text } from "@cocalc/frontend/components";19import { labels } from "@cocalc/frontend/i18n";20import * as LS from "@cocalc/frontend/misc/local-storage-typed";21import { webapp_client } from "@cocalc/frontend/webapp-client";22import { once } from "@cocalc/util/async-utils";23import { COLORS } from "@cocalc/util/theme";2425const VERIFY_EMAIL_STYLE: CSS = {26width: "100%",27padding: "5px",28borderBottom: `1px solid ${COLORS.GRAY_D}`,29background: COLORS.ATND_BG_RED_L,30} as const;3132const DISMISSED_KEY_LS = "verify-email-dismissed";3334export function VerifyEmail() {35const intl = useIntl();36const page_actions = useActions("page");37const email_address = useTypedRedux("account", "email_address");3839const [error, setError] = useState<string>("");40const [show, setShow] = useState<boolean>(true);41const [sending, setSending] = useState<boolean>(false);42const [sent, setSent] = useState<boolean>(false);4344async function verify(): Promise<void> {45try {46setSending(true);47await webapp_client.account_client.send_verification_email();48} catch (err) {49const errMsg = `Problem sending email verification: ${err}`;50setError(errMsg);51} finally {52setSent(true);53}54}5556// TODO: at one point this should be a popup to just edit the email address57function edit() {58page_actions.set_active_tab("account");59}6061function dismiss() {62const now = webapp_client.server_time().getTime();63LS.set(DISMISSED_KEY_LS, now);64setShow(false);65}6667function renderBanner() {68if (error) {69return <Text type="danger">{error}</Text>;70}71return (72<Text strong>73<Icon name="mail" />{" "}74<FormattedMessage75id="app.verify-email-banner.text"76defaultMessage={`{sent, select,77true {Sent! Plesae check your email inbox (maybe spam) and click on the confirmation link.}78other {Please check and verify your email address: <code>{email}</code>}}`}79values={{80sent,81email: email_address,82code: (c) => <Text code>{c}</Text>,83}}84/>{" "}85{sent ? (86<Button87onClick={() => setShow(false)}88bsStyle="success"89bsSize={"xsmall"}90>91{intl.formatMessage(labels.close)}92</Button>93) : (94<Space size={"small"}>95<Button bsSize={"xsmall"} onClick={edit}>96<Icon name="pencil" /> {intl.formatMessage(labels.edit)}97</Button>98<Button99onClick={verify}100bsStyle="success"101disabled={sent || sending}102bsSize={"xsmall"}103>104{intl.formatMessage(emailVerificationMsg, {105disabled_button: sent,106})}107</Button>108<HelpIcon109title={intl.formatMessage({110id: "app.verify-email-banner.help.title",111defaultMessage: "Email Verification",112})}113>114<FormattedMessage115id="app.verify-email-banner.help.text"116defaultMessage="It's important to have a working email address. We use this for password resets, sending messages, billing notifications, and support. Please ensure your email is correct to stay informed."117/>118</HelpIcon>119</Space>120)}121</Text>122);123}124125if (!show) return;126127return (128<div style={VERIFY_EMAIL_STYLE}>129{renderBanner()}130<CloseX2 close={dismiss} />131</div>132);133}134135export function useShowVerifyEmail(): boolean {136const email_address = useTypedRedux("account", "email_address");137const email_address_verified = useTypedRedux(138"account",139"email_address_verified",140);141const [loaded, setLoaded] = useState<boolean>(false);142143// wait until the account settings are loaded to show the banner144useAsyncEffect(async () => {145const store = redux.getStore("account");146if (!store.get("is_ready")) {147await once(store, "is_ready");148}149setLoaded(true);150}, []);151152const created = useTypedRedux("account", "created");153154const dismissedTS = LS.get<number>(DISMISSED_KEY_LS);155156const show_verify_email =157!email_address || !email_address_verified?.get(email_address);158159// we also do not show this for newly created accounts160const now = webapp_client.server_time().getTime();161const oneDay = 1 * 24 * 60 * 60 * 1000;162const notTooNew = created != null && now > created.getTime() + oneDay;163164// dismissed banner works for a week165const dismissed =166typeof dismissedTS === "number" && now < dismissedTS + 7 * oneDay;167168return show_verify_email && loaded && notTooNew && !dismissed;169}170171172