account delete link

This commit is contained in:
adueck 2024-04-02 19:10:12 +03:00
parent 1a2a36090f
commit d5f2aa492a
2 changed files with 279 additions and 206 deletions

View File

@ -12,9 +12,8 @@
</script> </script>
</head> </head>
<body> <body>
<div class="container" style="max-width: 400px;"> <div class="container" style="max-width: 800px;">
<h2 class="mt-4 mb-4 text-center">How to Delete your LingDocs Account</h2> <h2 class="mt-4 mb-4 text-center">How to Delete your LingDocs Account</h2>
<h4>Profile <i class="fas fa-user ml-2"></i></h4>
<p>To delete your account for the LingDocs Pashto Dictionary and LingDocs Pashto Grammar:</p> <p>To delete your account for the LingDocs Pashto Dictionary and LingDocs Pashto Grammar:</p>
<ul> <ul>
<li>Go to <a href="https://account.lingdocs.com/user">https://account.lingdocs.com/user</a></li> <li>Go to <a href="https://account.lingdocs.com/user">https://account.lingdocs.com/user</a></li>

View File

@ -1,7 +1,4 @@
import { import { useState, useEffect } from "react";
useState,
useEffect,
} from "react";
import { Modal, Button } from "react-bootstrap"; import { Modal, Button } from "react-bootstrap";
import { import {
upgradeAccount, upgradeAccount,
@ -13,21 +10,34 @@ import { Helmet } from "react-helmet";
import * as AT from "../types/account-types"; import * as AT from "../types/account-types";
import UpgradePrices from "../components/UpgradePrices"; import UpgradePrices from "../components/UpgradePrices";
const providers: ("google" | "twitter" | "github")[] = ["google", "twitter", "github"]; const providers: ("google" | "twitter" | "github")[] = [
"google",
"twitter",
"github",
];
const capitalize = (s: string): string => { const capitalize = (s: string): string => {
// if (!s) return ""; // if (!s) return "";
return s.charAt(0).toUpperCase() + s.slice(1); return s.charAt(0).toUpperCase() + s.slice(1);
} };
let popupRef: Window | null = null; let popupRef: Window | null = null;
const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUser: () => void }) => { const Account = ({
const [showingUpgradePrompt, setShowingUpgradePrompt] = useState<boolean>(false); user,
loadUser,
}: {
user: AT.LingdocsUser | undefined;
loadUser: () => void;
}) => {
const [showingUpgradePrompt, setShowingUpgradePrompt] =
useState<boolean>(false);
const [upgradePassword, setUpgradePassword] = useState<string>(""); const [upgradePassword, setUpgradePassword] = useState<string>("");
const [upgradeError, setUpgradeError] = useState<string>(""); const [upgradeError, setUpgradeError] = useState<string>("");
const [waiting, setWaiting] = useState<boolean>(false); const [waiting, setWaiting] = useState<boolean>(false);
const [publishingStatus, setPublishingStatus] = useState<undefined | "publishing" | any>(undefined); const [publishingStatus, setPublishingStatus] = useState<
undefined | "publishing" | any
>(undefined);
useEffect(() => { useEffect(() => {
setShowingUpgradePrompt(false); setShowingUpgradePrompt(false);
setUpgradeError(""); setUpgradeError("");
@ -41,9 +51,9 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
// TODO put the account url in an imported constant // TODO put the account url in an imported constant
function handleIncomingMessage(event: MessageEvent<any>) { function handleIncomingMessage(event: MessageEvent<any>) {
if ( if (
event.origin === "https://account.lingdocs.com" event.origin === "https://account.lingdocs.com" &&
&& (event.data === "signed in") event.data === "signed in" &&
&& popupRef popupRef
) { ) {
loadUser(); loadUser();
popupRef.close(); popupRef.close();
@ -61,7 +71,8 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
async function handleUpgrade() { async function handleUpgrade() {
setUpgradeError(""); setUpgradeError("");
setWaiting(true); setWaiting(true);
upgradeAccount(upgradePassword).then((res) => { upgradeAccount(upgradePassword)
.then((res) => {
setWaiting(false); setWaiting(false);
if (res.ok) { if (res.ok) {
loadUser(); loadUser();
@ -69,65 +80,102 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
} else { } else {
setUpgradeError("Incorrect password"); setUpgradeError("Incorrect password");
} }
}).catch((err) => { })
.catch((err) => {
setWaiting(false); setWaiting(false);
setUpgradeError(err.message); setUpgradeError(err.message);
}); });
} }
function handleOpenSignup() { function handleOpenSignup() {
popupRef = window.open("https://account.lingdocs.com", "account", "height=800,width=500,top=50,left=400"); popupRef = window.open(
"https://account.lingdocs.com",
"account",
"height=800,width=500,top=50,left=400"
);
} }
function handlePublish() { function handlePublish() {
setPublishingStatus("publishing"); setPublishingStatus("publishing");
publishDictionary().then((response) => { publishDictionary()
.then((response) => {
setPublishingStatus(response); setPublishingStatus(response);
}).catch((err) => { })
.catch((err) => {
console.error(err); console.error(err);
setPublishingStatus("Offline or connection error"); setPublishingStatus("Offline or connection error");
}); });
} }
if (!user) { if (!user) {
return <div className="text-center mt-3"> return (
<div className="text-center mt-3">
<Helmet> <Helmet>
<link rel="canonical" href="https://dictionary.lingdocs.com/account" /> <link
<meta name="description" content="Sign in to the LingDocs Pashto Dictionary" /> rel="canonical"
href="https://dictionary.lingdocs.com/account"
/>
<meta
name="description"
content="Sign in to the LingDocs Pashto Dictionary"
/>
<title>Sign In - LingDocs Pashto Dictionary</title> <title>Sign In - LingDocs Pashto Dictionary</title>
</Helmet> </Helmet>
<h2 className="my-4">Sign in to LingDocs</h2> <h2 className="my-4">Sign in to LingDocs</h2>
<p className="lead mb-4">When you sign in or make a LingDocs account you can:</p> <p className="lead mb-4">
<div className="mb-3"><i className="fas fa-pen mr-2" /> contribute by suggesting corrections and new words</div> When you sign in or make a LingDocs account you can:
<div className="mb-3"><i className="fas fa-star mr-2" /> upgrade your account and start collecting a personal <strong>wordlist</strong></div> </p>
<button className="btn btn-lg btn-primary my-4" onClick={handleOpenSignup}><i className="fas fa-sign-in-alt mr-2" /> Sign In</button> <div className="mb-3">
<i className="fas fa-pen mr-2" /> contribute by suggesting corrections
and new words
</div> </div>
<div className="mb-3">
<i className="fas fa-star mr-2" /> upgrade your account and start
collecting a personal <strong>wordlist</strong>
</div>
<button
className="btn btn-lg btn-primary my-4"
onClick={handleOpenSignup}
>
<i className="fas fa-sign-in-alt mr-2" /> Sign In
</button>
</div>
);
} }
return ( return (
<div style={{ marginBottom: "100px", maxWidth: "40rem" }}> <div style={{ marginBottom: "100px", maxWidth: "40rem" }}>
<Helmet> <Helmet>
<link rel="canonical" href="https://dictionary.lingdocs.com/account" /> <link rel="canonical" href="https://dictionary.lingdocs.com/account" />
<meta name="description" content="Account for the LingDocs Pashto Dictionary" /> <meta
name="description"
content="Account for the LingDocs Pashto Dictionary"
/>
<title>Account - LingDocs Pashto Dictionary</title> <title>Account - LingDocs Pashto Dictionary</title>
</Helmet> </Helmet>
<h2 className="mb-4">Account</h2> <h2 className="mb-4">Account</h2>
{user.level === "editor" && {user.level === "editor" && (
<div className="mb-3"> <div className="mb-3">
<h4>Editor Tools</h4> <h4>Editor Tools</h4>
{publishingStatus !== "publishing" && {publishingStatus !== "publishing" && (
<button type="button" className="btn btn-secondary" onClick={handlePublish}>Publish Dictionary</button> <button
} type="button"
{publishingStatus && className="btn btn-secondary"
onClick={handlePublish}
>
Publish Dictionary
</button>
)}
{publishingStatus && (
<> <>
<h6 className="mt-3">Publishing response:</h6> <h6 className="mt-3">Publishing response:</h6>
<pre className="pre-scrollable"><code> <pre className="pre-scrollable">
{publishingStatus === "publishing" ? <code>
"processing..." {publishingStatus === "publishing"
: ? "processing..."
JSON.stringify(publishingStatus, null, "\t") : JSON.stringify(publishingStatus, null, "\t")}
} </code>
</code></pre> </pre>
</> </>
} )}
</div> </div>
} )}
<div> <div>
{/* {user.p && <div className="mb-4 mt-3" style={{ textAlign: "center" }}> {/* {user.p && <div className="mb-4 mt-3" style={{ textAlign: "center" }}>
<img src={user.photoURL} data-testid="userAvatar" alt="avatar" style={{ borderRadius: "50%", width: "5rem", height: "5rem" }}/> <img src={user.photoURL} data-testid="userAvatar" alt="avatar" style={{ borderRadius: "50%", width: "5rem", height: "5rem" }}/>
@ -135,21 +183,31 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
<div className="card mb-4"> <div className="card mb-4">
<ul className="list-group list-group-flush"> <ul className="list-group list-group-flush">
<li className="list-group-item">Name: {user.name}</li> <li className="list-group-item">Name: {user.name}</li>
{user.email && <li className="list-group-item"> {user.email && (
<li className="list-group-item">
<div className="d-flex justify-content-between align-items-center"> <div className="d-flex justify-content-between align-items-center">
<div> <div>
<div>Email: {user.email}</div> <div>Email: {user.email}</div>
</div> </div>
</div> </div>
</li>} </li>
<li className="list-group-item">Account Level: {capitalize(user.level)}</li> )}
<li className="list-group-item">Signs in with: <li className="list-group-item">
{(user.password && user.email) && <span> Account Level: {capitalize(user.level)}
<i className="fas fa-key ml-2"></i> <span className="small mr-1">Password</span> </li>
</span>} <li className="list-group-item">
Signs in with:
{user.password && user.email && (
<span>
<i className="fas fa-key ml-2"></i>{" "}
<span className="small mr-1">Password</span>
</span>
)}
{providers.map((provider) => ( {providers.map((provider) => (
<span key={provider}> <span key={provider}>
{user[provider] && <i className={`fab fa-${provider} mx-1`}></i>} {user[provider] && (
<i className={`fab fa-${provider} mx-1`}></i>
)}
</span> </span>
))} ))}
</li> </li>
@ -158,7 +216,8 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
</div> </div>
<h4 className="mb-3">Account Admin</h4> <h4 className="mb-3">Account Admin</h4>
<div className="row mb-4"> <div className="row mb-4">
{user.level === "basic" && <div className="col-sm mb-3"> {user.level === "basic" && (
<div className="col-sm mb-3">
<button <button
type="button" type="button"
className="btn btn-outline-secondary" className="btn btn-outline-secondary"
@ -167,9 +226,13 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
> >
<i className="fa fa-level-up-alt"></i> Upgrade Account <i className="fa fa-level-up-alt"></i> Upgrade Account
</button> </button>
</div>} </div>
)}
<div className="col-sm mb-3"> <div className="col-sm mb-3">
<a className="btn btn-outline-secondary" href="https://account.lingdocs.com/user"> <a
className="btn btn-outline-secondary"
href="https://account.lingdocs.com/user"
>
<i className="fas fa-user mr-2"></i> Edit Account <i className="fas fa-user mr-2"></i> Edit Account
</a> </a>
</div> </div>
@ -179,12 +242,19 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
</button> </button>
</div> </div>
</div> </div>
<div>
<a className="small" href="https://account.lingdocs.com/delete-account">
How to delete your account
</a>
</div>
<Modal show={showingUpgradePrompt} onHide={closeUpgrade}> <Modal show={showingUpgradePrompt} onHide={closeUpgrade}>
<Modal.Header closeButton> <Modal.Header closeButton>
<Modal.Title>Upgrade to Student Account</Modal.Title> <Modal.Title>Upgrade to Student Account</Modal.Title>
</Modal.Header> </Modal.Header>
<Modal.Body> <Modal.Body>
<p className="lead">Upgrade to a <strong>student account</strong> to enable the wordlist</p> <p className="lead">
Upgrade to a <strong>student account</strong> to enable the wordlist
</p>
<p>Features:</p> <p>Features:</p>
<ul> <ul>
<li>Save your wordlist and sync across devices</li> <li>Save your wordlist and sync across devices</li>
@ -194,7 +264,9 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
<UpgradePrices source="account" /> <UpgradePrices source="account" />
</Modal.Body> </Modal.Body>
<div className="form-group px-3"> <div className="form-group px-3">
<label htmlFor="upgradePasswordForm">Or enter upgrade password:</label> <label htmlFor="upgradePasswordForm">
Or enter upgrade password:
</label>
<input <input
type="text" type="text"
className="form-control" className="form-control"
@ -204,11 +276,13 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
onChange={(e) => setUpgradePassword(e.target.value)} onChange={(e) => setUpgradePassword(e.target.value)}
/> />
</div> </div>
{upgradeError && <div className="mt-3 alert alert-warning mx-3"> {upgradeError && (
<div className="mt-3 alert alert-warning mx-3">
<p> <p>
<strong>{upgradeError}</strong> <strong>{upgradeError}</strong>
</p> </p>
</div>} </div>
)}
<Modal.Footer> <Modal.Footer>
{waiting && <LoadingElipses />} {waiting && <LoadingElipses />}
<Button variant="secondary" onClick={closeUpgrade}> <Button variant="secondary" onClick={closeUpgrade}>