thuang-1840-authn-prompt (#1911)

This commit is contained in:
Timmy Huang
2020-10-08 16:57:53 -07:00
committed by GitHub
parent 6677d0de56
commit c01a2c72b6
3 changed files with 117 additions and 28 deletions
+91 -5
View File
@@ -1,4 +1,5 @@
import React from "react";
import React, { useState } from "react";
import {
AnchorButton,
Button,
@@ -6,20 +7,36 @@ import {
Tooltip,
Popover,
Menu,
Elevation,
PopoverPosition,
Checkbox,
Card,
} from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import * as globals from "../../globals";
import styles from "./menubar.css";
import { storageGet, storageSet, KEYS } from "../util/localStorage";
const BASE_EMOJI = [0x1f9d1, 0x1f468, 0x1f469];
const SKIN_TONES = [0x1f3fb, 0x1f3fc, 0x1f3fd, 0x1f3fe, 0x1f3ff];
const MICROSCOPE = 0x1f52c;
const ZERO_WIDTH_JOINER = 0x0200d;
const LOGIN_PROMPT_OFF = "off";
const Auth = React.memo((props) => {
const [isPromptOpen, setIsPromptOpen] = useState(shouldShowPrompt());
const { auth, userinfo } = props;
const isAuthenticated = userinfo && userinfo.is_authenticated;
window.userinfo = userinfo;
const randomInt = Math.random() * 15;
const sexIndex = Math.floor(randomInt / 5);
const skinToneIndex = Math.floor(randomInt % 5);
@@ -31,9 +48,9 @@ const Auth = React.memo((props) => {
MICROSCOPE
);
if (!auth?.["requires_client_login"]) return null;
if (!shouldShowAuth()) return null;
if (userinfo?.["is_authenticated"]) {
if (isAuthenticated) {
const PopoverContent = (
<Menu>
<MenuItem
@@ -67,7 +84,7 @@ const Auth = React.memo((props) => {
);
}
return (
const LoginButton = (
<Tooltip
content="Log in to cellxgene"
position="bottom"
@@ -76,7 +93,6 @@ const Auth = React.memo((props) => {
<AnchorButton
type="button"
data-testid="log-in"
disabled={false}
href={auth.login}
className={styles.menubarButton}
>
@@ -84,6 +100,76 @@ const Auth = React.memo((props) => {
</AnchorButton>
</Tooltip>
);
if (isPromptOpen) {
return (
<Popover
position={PopoverPosition.AUTO_END}
isOpen
content={<PromptContent setIsPromptOpen={setIsPromptOpen} />}
onInteraction={setIsPromptOpen}
>
{LoginButton}
</Popover>
);
}
return LoginButton;
function shouldShowAuth() {
return auth && auth.requires_client_login;
}
function shouldShowPrompt() {
if (storageGet(KEYS.LOGIN_PROMPT) === LOGIN_PROMPT_OFF) return false;
return shouldShowAuth && !isAuthenticated;
}
});
function PromptContent({ setIsPromptOpen }) {
const [isChecked, setIsChecked] = useState(false);
function handleOKClick() {
if (isChecked) {
storageSet(KEYS.LOGIN_PROMPT, LOGIN_PROMPT_OFF);
}
setIsPromptOpen(false);
}
function handleCheckboxChange() {
setIsChecked(!isChecked);
}
return (
<Card style={{ width: "500px" }} elevation={Elevation.TWO}>
<p>
Logging in will enable you to create your own categories and labels.
Logging in later will reset cellxgene to the default view and cause you
to lose progress.
</p>
<Checkbox
style={{ width: "230px" }}
checked={isChecked}
onChange={handleCheckboxChange}
data-testid="login-hint-do-not-show-again"
>
Do not show me this message again
</Checkbox>
<div
style={{ display: "flex", justifyContent: "flex-end", marginTop: 15 }}
>
<Button
onClick={handleOKClick}
intent="primary"
data-testid="login-hint-yes"
>
Acknowledge
</Button>
</div>
</Card>
);
}
export default Auth;
+4 -23
View File
@@ -8,26 +8,7 @@ import {
Colors,
Icon,
} from "@blueprintjs/core";
const CookieDecision = "cxg.cookieDecision";
function storageGet(key, defaultValue = null) {
try {
const val = window.localStorage.getItem(key);
if (val === null) return defaultValue;
return val;
} catch (e) {
return defaultValue;
}
}
function storageSet(key, value) {
try {
window.localStorage.setItem(key, value);
} catch {
// continue
}
}
import { storageGet, storageSet, KEYS } from "../util/localStorage";
@connect((state) => ({
tosURL: state.config?.parameters?.["about_legal_tos"],
@@ -37,7 +18,7 @@ class TermsPrompt extends React.PureComponent {
constructor(props) {
super(props);
const { tosURL, privacyURL } = this.props;
const cookieDecision = storageGet(CookieDecision, null);
const cookieDecision = storageGet(KEYS.COOKIE_DECISION, null);
const hasDecided = cookieDecision !== null;
this.state = {
hasDecided,
@@ -55,7 +36,7 @@ class TermsPrompt extends React.PureComponent {
handleOK = () => {
this.setState({ isOpen: false });
storageSet(CookieDecision, "yes");
storageSet(KEYS.COOKIE_DECISION, "yes");
if (window.cookieDecisionCallback instanceof Function) {
try {
window.cookieDecisionCallback();
@@ -67,7 +48,7 @@ class TermsPrompt extends React.PureComponent {
handleNo = () => {
this.setState({ isOpen: false });
storageSet(CookieDecision, "no");
storageSet(KEYS.COOKIE_DECISION, "no");
};
renderTos() {
@@ -0,0 +1,22 @@
export const KEYS = {
COOKIE_DECISION: "cxg.cookieDecision",
LOGIN_PROMPT: "cxg.LOGIN_PROMPT",
};
export function storageGet(key, defaultValue = null) {
try {
const val = window.localStorage.getItem(key);
if (val === null) return defaultValue;
return val;
} catch (e) {
return defaultValue;
}
}
export function storageSet(key, value) {
try {
window.localStorage.setItem(key, value);
} catch {
// continue
}
}