1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36:40 +07:00

removed all router-modals

This commit is contained in:
Fedor Katurov 2022-01-09 20:27:23 +07:00
parent 85d20e5009
commit ffce400398
15 changed files with 99 additions and 143 deletions

View file

@ -1,26 +1,26 @@
import React, { FC, useCallback, useState } from 'react'; import React, { FC, useCallback, useState } from 'react';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import { Link } from 'react-router-dom';
import classNames from 'classnames'; import classNames from 'classnames';
import { useRouteMatch } from 'react-router';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { useShowModal } from '~/hooks/modal/useShowModal';
import { Dialog } from '~/constants/modal';
interface Props { interface Props {
isLab?: boolean; isLab?: boolean;
} }
const SubmitBar: FC<Props> = ({ isLab }) => { const SubmitBar: FC<Props> = ({ isLab }) => {
const { url } = useRouteMatch(); const showModal = useShowModal(Dialog.CreateNode);
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const onFocus = useCallback(() => setFocused(true), [setFocused]); const onFocus = useCallback(() => setFocused(true), [setFocused]);
const onBlur = useCallback(() => setFocused(false), [setFocused]); const onBlur = useCallback(() => setFocused(false), [setFocused]);
const createUrl = useCallback( const createUrl = useCallback(
(type: string) => { (type: string) => () => {
return [url.replace(/\/$/, ''), 'create', type].join('/'); showModal({ type, isInLab: !!isLab });
}, },
[url] [isLab, showModal]
); );
const icon = isLab ? 'lab' : 'plus'; const icon = isLab ? 'lab' : 'plus';
@ -28,21 +28,21 @@ const SubmitBar: FC<Props> = ({ isLab }) => {
return ( return (
<div className={classNames(styles.wrap, { [styles.lab]: isLab })}> <div className={classNames(styles.wrap, { [styles.lab]: isLab })}>
<div className={classNames(styles.panel, { [styles.active]: focused })}> <div className={classNames(styles.panel, { [styles.active]: focused })}>
<Link to={createUrl('image')} className={styles.link}> <button onClick={createUrl('image')} className={styles.link}>
<Icon icon="image" size={32} /> <Icon icon="image" size={32} />
</Link> </button>
<Link to={createUrl('text')} className={styles.link}> <button onClick={createUrl('text')} className={styles.link}>
<Icon icon="text" size={32} /> <Icon icon="text" size={32} />
</Link> </button>
<Link to={createUrl('video')} className={styles.link}> <button onClick={createUrl('video')} className={styles.link}>
<Icon icon="video" size={32} /> <Icon icon="video" size={32} />
</Link> </button>
<Link to={createUrl('audio')} className={styles.link}> <button onClick={createUrl('audio')} className={styles.link}>
<Icon icon="audio" size={32} /> <Icon icon="audio" size={32} />
</Link> </button>
</div> </div>
<button className={styles.button} onFocus={onFocus} onBlur={onBlur} type="button"> <button className={styles.button} onFocus={onFocus} onBlur={onBlur} type="button">

View file

@ -27,6 +27,7 @@ interface IProps {
onLike: () => void; onLike: () => void;
onStar: () => void; onStar: () => void;
onLock: () => void; onLock: () => void;
onEdit: () => void;
} }
const NodeTitle: VFC<IProps> = memo( const NodeTitle: VFC<IProps> = memo(
@ -50,6 +51,7 @@ const NodeTitle: VFC<IProps> = memo(
onStar, onStar,
onLike, onLike,
onLock, onLock,
onEdit,
}) => { }) => {
return ( return (
<div className={classNames(styles.wrap)}> <div className={classNames(styles.wrap)}>
@ -91,11 +93,7 @@ const NodeTitle: VFC<IProps> = memo(
<Icon icon={isLocked ? 'locked' : 'unlocked'} size={24} onClick={onLock} /> <Icon icon={isLocked ? 'locked' : 'unlocked'} size={24} onClick={onLock} />
</div> </div>
{!!id && ( {!!id && <Icon icon="edit" size={24} onClick={onEdit} />}
<Link to={URLS.NODE_EDIT_URL(id)}>
<Icon icon="edit" size={24} />
</Link>
)}
</div> </div>
</div> </div>
)} )}

View file

@ -6,6 +6,9 @@ import { ProfileDialog } from '~/containers/dialogs/ProfileDialog';
import { RestoreRequestDialog } from '~/containers/dialogs/RestoreRequestDialog'; import { RestoreRequestDialog } from '~/containers/dialogs/RestoreRequestDialog';
import { RestorePasswordDialog } from '~/containers/dialogs/RestorePasswordDialog'; import { RestorePasswordDialog } from '~/containers/dialogs/RestorePasswordDialog';
import { PhotoSwipe } from '~/containers/dialogs/PhotoSwipe'; import { PhotoSwipe } from '~/containers/dialogs/PhotoSwipe';
import { EditorCreateDialog } from '~/containers/dialogs/EditorCreateDialog';
import { EditorEditDialog } from '~/containers/dialogs/EditorEditDialog';
import { TagSidebar } from '~/containers/sidebars/TagSidebar';
export enum Dialog { export enum Dialog {
Login = 'Login', Login = 'Login',
@ -16,6 +19,9 @@ export enum Dialog {
RestorePassword = 'RestorePassword', RestorePassword = 'RestorePassword',
Test = 'Test', Test = 'Test',
Photoswipe = 'Photoswipe', Photoswipe = 'Photoswipe',
CreateNode = 'CreateNode',
EditNode = 'EditNode',
TagSidebar = 'TagNodes',
} }
export const DIALOG_CONTENT = { export const DIALOG_CONTENT = {
@ -27,4 +33,7 @@ export const DIALOG_CONTENT = {
[Dialog.RestoreRequest]: RestoreRequestDialog, [Dialog.RestoreRequest]: RestoreRequestDialog,
[Dialog.RestorePassword]: RestorePasswordDialog, [Dialog.RestorePassword]: RestorePasswordDialog,
[Dialog.Photoswipe]: PhotoSwipe, [Dialog.Photoswipe]: PhotoSwipe,
[Dialog.CreateNode]: EditorCreateDialog,
[Dialog.EditNode]: EditorEditDialog,
[Dialog.TagSidebar]: TagSidebar,
} as const; } as const;

View file

@ -1,30 +1,19 @@
import React, { FC, useCallback, useMemo, useRef } from 'react'; import React, { FC, useCallback, useMemo, useRef } from 'react';
import { EMPTY_NODE, NODE_TYPES } from '~/constants/node'; import { EMPTY_NODE, NODE_TYPES } from '~/constants/node';
import { EditorDialog } from '~/containers/dialogs/EditorDialog'; import { EditorDialog } from '~/containers/dialogs/EditorDialog';
import { useHistory, useRouteMatch } from 'react-router';
import { values } from 'ramda'; import { values } from 'ramda';
import { INode } from '~/types'; import { INode } from '~/types';
import { useCreateNode } from '~/hooks/node/useCreateNode'; import { useCreateNode } from '~/hooks/node/useCreateNode';
import { DialogComponentProps } from '~/types/modal';
const EditorCreateDialog: FC = () => { export interface EditorCreateDialogProps extends DialogComponentProps {
const history = useHistory(); type: typeof NODE_TYPES[keyof typeof NODE_TYPES];
const { isInLab: boolean;
params: { type }, }
url,
} = useRouteMatch<{ type: string }>();
const backUrl = useMemo(() => {
return (url && url.replace(/\/create\/(.*)$/, '')) || '/';
}, [url]);
const goBack = useCallback(() => {
history.replace(backUrl);
}, [backUrl, history]);
const EditorCreateDialog: FC<EditorCreateDialogProps> = ({ type, isInLab, onRequestClose }) => {
const isExist = useMemo(() => values(NODE_TYPES).some(el => el === type), [type]); const isExist = useMemo(() => values(NODE_TYPES).some(el => el === type), [type]);
const isInLab = useMemo(() => !!url.match(/^\/lab/), [url]);
const data = useRef({ ...EMPTY_NODE, type, is_promoted: !isInLab }); const data = useRef({ ...EMPTY_NODE, type, is_promoted: !isInLab });
const createNode = useCreateNode(); const createNode = useCreateNode();
@ -32,16 +21,16 @@ const EditorCreateDialog: FC = () => {
const onSubmit = useCallback( const onSubmit = useCallback(
async (node: INode) => { async (node: INode) => {
await createNode(node); await createNode(node);
goBack(); onRequestClose();
}, },
[goBack, createNode] [onRequestClose, createNode]
); );
if (!type || !isExist) { if (!type || !isExist) {
return null; return null;
} }
return <EditorDialog node={data.current} onRequestClose={goBack} onSubmit={onSubmit} />; return <EditorDialog node={data.current} onRequestClose={onRequestClose} onSubmit={onSubmit} />;
}; };
export { EditorCreateDialog }; export { EditorCreateDialog };

View file

@ -1,7 +1,7 @@
import React, { createElement, FC, useCallback, useMemo, useState } from 'react'; import React, { createElement, FC, useCallback, useMemo, useState } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { NODE_EDITORS } from '~/constants/node'; import { NODE_EDITORS } from '~/constants/node';
import { BetterScrollDialog } from '../../../components/dialogs/BetterScrollDialog'; import { BetterScrollDialog } from '~/components/dialogs/BetterScrollDialog';
import { CoverBackdrop } from '~/components/containers/CoverBackdrop'; import { CoverBackdrop } from '~/components/containers/CoverBackdrop';
import { prop } from 'ramda'; import { prop } from 'ramda';
import { useNodeFormFormik } from '~/hooks/node/useNodeFormFormik'; import { useNodeFormFormik } from '~/hooks/node/useNodeFormFormik';
@ -9,8 +9,6 @@ import { EditorButtons } from '~/components/editors/EditorButtons';
import { UploadSubject, UploadTarget } from '~/constants/uploads'; import { UploadSubject, UploadTarget } from '~/constants/uploads';
import { FormikProvider } from 'formik'; import { FormikProvider } from 'formik';
import { INode } from '~/types'; import { INode } from '~/types';
import { ModalWrapper } from '~/components/dialogs/ModalWrapper';
import { useTranslatedError } from '~/hooks/data/useTranslatedError';
import { useCloseOnEscape } from '~/hooks'; import { useCloseOnEscape } from '~/hooks';
import { EditorConfirmClose } from '~/components/editors/EditorConfirmClose'; import { EditorConfirmClose } from '~/components/editors/EditorConfirmClose';
import { DialogComponentProps } from '~/types/modal'; import { DialogComponentProps } from '~/types/modal';
@ -50,8 +48,6 @@ const EditorDialog: FC<Props> = observer(({ node, onRequestClose, onSubmit }) =>
setConfirmModalShown(true); setConfirmModalShown(true);
}, [dirty, isConfirmModalShown, onRequestClose, closeConfirmModal]); }, [dirty, isConfirmModalShown, onRequestClose, closeConfirmModal]);
const error = useTranslatedError(status);
useCloseOnEscape(onClose); useCloseOnEscape(onClose);
if (!component) { if (!component) {
@ -59,29 +55,26 @@ const EditorDialog: FC<Props> = observer(({ node, onRequestClose, onSubmit }) =>
} }
return ( return (
<ModalWrapper onOverlayClick={onClose}> <UploaderContextProvider value={uploader}>
<UploaderContextProvider value={uploader}> <FormikProvider value={formik}>
<FormikProvider value={formik}> <form onSubmit={handleSubmit} className={styles.form}>
<form onSubmit={handleSubmit} className={styles.form}> <BetterScrollDialog
<BetterScrollDialog footer={<EditorButtons />}
footer={<EditorButtons />} backdrop={<CoverBackdrop cover={values.cover} />}
backdrop={<CoverBackdrop cover={values.cover} />} width={860}
width={860} onClose={onClose}
error={error} >
onClose={onClose} <>
> {isConfirmModalShown && (
<> <EditorConfirmClose onApprove={onRequestClose} onDecline={closeConfirmModal} />
{isConfirmModalShown && ( )}
<EditorConfirmClose onApprove={onRequestClose} onDecline={closeConfirmModal} />
)}
<div className={styles.editor}>{createElement(component)}</div> <div className={styles.editor}>{createElement(component)}</div>
</> </>
</BetterScrollDialog> </BetterScrollDialog>
</form> </form>
</FormikProvider> </FormikProvider>
</UploaderContextProvider> </UploaderContextProvider>
</ModalWrapper>
); );
}); });

View file

@ -1,6 +1,5 @@
import React, { FC, useCallback, useMemo } from 'react'; import React, { FC, useCallback } from 'react';
import { EditorDialog } from '~/containers/dialogs/EditorDialog'; import { EditorDialog } from '~/containers/dialogs/EditorDialog';
import { useHistory, useRouteMatch } from 'react-router';
import { ModalWrapper } from '~/components/dialogs/ModalWrapper'; import { ModalWrapper } from '~/components/dialogs/ModalWrapper';
import { LoaderCircle } from '~/components/input/LoaderCircle'; import { LoaderCircle } from '~/components/input/LoaderCircle';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
@ -8,37 +7,27 @@ import { useLoadNode } from '~/hooks/node/useLoadNode';
import { useUpdateNode } from '~/hooks/node/useUpdateNode'; import { useUpdateNode } from '~/hooks/node/useUpdateNode';
import { INode } from '~/types'; import { INode } from '~/types';
import { observer } from 'mobx-react-lite'; import { observer } from 'mobx-react-lite';
import { DialogComponentProps } from '~/types/modal';
const EditorEditDialog: FC = observer(() => { export interface EditorEditDialogProps extends DialogComponentProps {
const history = useHistory(); nodeId: number;
}
const { const EditorEditDialog: FC<EditorEditDialogProps> = observer(({ nodeId, onRequestClose }) => {
params: { id }, const { node, isLoading } = useLoadNode(nodeId);
url, const updateNode = useUpdateNode(nodeId);
} = useRouteMatch<{ id: string }>();
const backUrl = useMemo(() => {
return url.replace(/\/edit$/, '');
}, [url]);
const goBack = useCallback(() => {
history.replace(backUrl);
}, [backUrl, history]);
const { node, isLoading } = useLoadNode(parseInt(id, 10));
const updateNode = useUpdateNode(parseInt(id, 10));
const onSubmit = useCallback( const onSubmit = useCallback(
async (node: INode) => { async (node: INode) => {
await updateNode(node); await updateNode(node);
goBack(); onRequestClose();
}, },
[updateNode, goBack] [updateNode, onRequestClose]
); );
if (isLoading || !node) { if (isLoading || !node) {
return ( return (
<ModalWrapper onOverlayClick={goBack}> <ModalWrapper onOverlayClick={onRequestClose}>
<div className={styles.loader}> <div className={styles.loader}>
<LoaderCircle size={64} /> <LoaderCircle size={64} />
</div> </div>
@ -46,7 +35,7 @@ const EditorEditDialog: FC = observer(() => {
); );
} }
return <EditorDialog node={node} onRequestClose={goBack} onSubmit={onSubmit} />; return <EditorDialog node={node} onRequestClose={onRequestClose} onSubmit={onSubmit} />;
}); });
export { EditorEditDialog }; export { EditorEditDialog };

View file

@ -4,7 +4,6 @@ import { Route, Switch } from 'react-router';
import { TagSidebar } from '~/containers/sidebars/TagSidebar'; import { TagSidebar } from '~/containers/sidebars/TagSidebar';
import { Authorized } from '~/components/containers/Authorized'; import { Authorized } from '~/components/containers/Authorized';
import { SubmitBar } from '~/components/bars/SubmitBar'; import { SubmitBar } from '~/components/bars/SubmitBar';
import { EditorCreateDialog } from '~/containers/dialogs/EditorCreateDialog';
interface IProps { interface IProps {
prefix?: string; prefix?: string;
@ -13,16 +12,9 @@ interface IProps {
const SidebarRouter: FC<IProps> = ({ prefix = '', isLab }) => { const SidebarRouter: FC<IProps> = ({ prefix = '', isLab }) => {
return createPortal( return createPortal(
<> <Authorized>
<Switch> <SubmitBar isLab={isLab} />
<Route path={`${prefix}/create/:type`} component={EditorCreateDialog} /> </Authorized>,
<Route path={`${prefix}/tag/:tag`} component={TagSidebar} />
</Switch>
<Authorized>
<SubmitBar isLab={isLab} />
</Authorized>
</>,
document.body document.body
); );
}; };

View file

@ -20,13 +20,10 @@ const SidebarWrapper: FC<IProps> = ({ children, onClose }) => {
return () => clearAllBodyScrollLocks(); return () => clearAllBodyScrollLocks();
}, []); }, []);
return createPortal( return (
<div className={styles.wrapper} ref={ref}> <div className={styles.wrapper} ref={ref}>
<div className={styles.clicker} onClick={onClose} />
{children} {children}
</div>, </div>
document.body
); );
}; };

View file

@ -10,9 +10,6 @@
} }
.wrapper { .wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
@ -22,19 +19,7 @@
overflow: hidden; overflow: hidden;
animation: appear 0.25s forwards; animation: appear 0.25s forwards;
@include sidebar;
& > * { & > * {
z-index: 4; z-index: 4;
} }
} }
.clicker {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
cursor: pointer;
}

View file

@ -1,7 +1,6 @@
import React, { useCallback, useMemo, VFC } from 'react'; import React, { useMemo, VFC } from 'react';
import { SidebarWrapper } from '~/containers/sidebars/SidebarWrapper'; import { SidebarWrapper } from '~/containers/sidebars/SidebarWrapper';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { useHistory, useRouteMatch } from 'react-router';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { TagSidebarList } from '~/components/sidebar/TagSidebarList'; import { TagSidebarList } from '~/components/sidebar/TagSidebarList';
@ -9,21 +8,18 @@ import { LoaderCircle } from '~/components/input/LoaderCircle';
import { InfiniteScroll } from '~/components/containers/InfiniteScroll'; import { InfiniteScroll } from '~/components/containers/InfiniteScroll';
import { Tag } from '~/components/tags/Tag'; import { Tag } from '~/components/tags/Tag';
import { useTagNodes } from '~/hooks/tag/useTagNodes'; import { useTagNodes } from '~/hooks/tag/useTagNodes';
import { DialogComponentProps } from '~/types/modal';
const TagSidebar: VFC = () => { interface TagSidebarProps extends DialogComponentProps {
const { tag: string;
params: { tag }, }
url,
} = useRouteMatch<{ tag: string }>();
const history = useHistory();
const basePath = url.replace(new RegExp(`/tag/${tag}$`), ''); const TagSidebar: VFC<TagSidebarProps> = ({ tag, onRequestClose }) => {
const onClose = useCallback(() => history.push(basePath), [basePath, history]);
const { nodes, hasMore, isLoading, loadMore } = useTagNodes(tag); const { nodes, hasMore, isLoading, loadMore } = useTagNodes(tag);
const title = useMemo(() => decodeURIComponent(tag), [tag]); const title = useMemo(() => decodeURIComponent(tag), [tag]);
return ( return (
<SidebarWrapper onClose={onClose}> <SidebarWrapper onClose={onRequestClose}>
<div className={styles.wrap}> <div className={styles.wrap}>
<div className={styles.content}> <div className={styles.content}>
<div className={styles.head}> <div className={styles.head}>
@ -38,9 +34,9 @@ const TagSidebar: VFC = () => {
)} )}
<div className={styles.close}> <div className={styles.close}>
<Link to={basePath}> <button onClick={onRequestClose}>
<Icon icon="close" size={32} /> <Icon icon="close" size={32} />
</Link> </button>
</div> </div>
</div> </div>

View file

@ -2,8 +2,12 @@ import { INode } from '~/types';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { apiLockNode, apiPostNodeHeroic, apiPostNodeLike } from '~/api/node'; import { apiLockNode, apiPostNodeHeroic, apiPostNodeLike } from '~/api/node';
import { showErrorToast } from '~/utils/errors/showToast'; import { showErrorToast } from '~/utils/errors/showToast';
import { useModal } from '~/hooks/modal/useModal';
import { Dialog } from '~/constants/modal';
export const useNodeActions = (node: INode, update: (node: Partial<INode>) => Promise<unknown>) => { export const useNodeActions = (node: INode, update: (node: Partial<INode>) => Promise<unknown>) => {
const { showModal } = useModal();
const onLike = useCallback(async () => { const onLike = useCallback(async () => {
try { try {
const result = await apiPostNodeLike({ id: node.id }); const result = await apiPostNodeLike({ id: node.id });
@ -37,5 +41,7 @@ export const useNodeActions = (node: INode, update: (node: Partial<INode>) => Pr
} }
}, [node.deleted_at, node.id, update]); }, [node.deleted_at, node.id, update]);
return { onLike, onStar, onLock }; const onEdit = useCallback(() => showModal(Dialog.EditNode, { nodeId: node.id! }), [node]);
return { onLike, onStar, onLock, onEdit };
}; };

View file

@ -1,15 +1,15 @@
import { useHistory } from 'react-router';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { ITag } from '~/types'; import { ITag } from '~/types';
import { URLS } from '~/constants/urls';
import { useLoadNode } from '~/hooks/node/useLoadNode'; import { useLoadNode } from '~/hooks/node/useLoadNode';
import { apiDeleteNodeTag, apiPostNodeTags } from '~/api/node'; import { apiDeleteNodeTag, apiPostNodeTags } from '~/api/node';
import { useGetNodeRelated } from '~/hooks/node/useGetNodeRelated'; import { useGetNodeRelated } from '~/hooks/node/useGetNodeRelated';
import { useShowModal } from '~/hooks/modal/useShowModal';
import { Dialog } from '~/constants/modal';
export const useNodeTags = (id: number) => { export const useNodeTags = (id: number) => {
const showModal = useShowModal(Dialog.TagSidebar);
const { refresh: refreshRelated } = useGetNodeRelated(id); const { refresh: refreshRelated } = useGetNodeRelated(id);
const { update } = useLoadNode(id); const { update } = useLoadNode(id);
const history = useHistory();
const onChange = useCallback( const onChange = useCallback(
async (tags: string[]) => { async (tags: string[]) => {
@ -30,9 +30,9 @@ export const useNodeTags = (id: number) => {
return; return;
} }
history.push(URLS.NODE_TAG_URL(id, encodeURIComponent(tag.title))); showModal({ tag: tag.title });
}, },
[history, id] [showModal, id]
); );
const onDelete = useCallback( const onDelete = useCallback(

View file

@ -24,7 +24,7 @@ const NodeLayout: FC<IProps> = () => {
const { node, isLoading, update } = useNodeContext(); const { node, isLoading, update } = useNodeContext();
const { head, block } = useNodeBlocks(node, isLoading); const { head, block } = useNodeBlocks(node, isLoading);
const [canEdit, canLike, canStar] = useNodePermissions(node); const [canEdit, canLike, canStar] = useNodePermissions(node);
const { onLike, onStar, onLock } = useNodeActions(node, update); const { onLike, onStar, onLock, onEdit } = useNodeActions(node, update);
useNodeCoverImage(node); useNodeCoverImage(node);
@ -53,6 +53,7 @@ const NodeLayout: FC<IProps> = () => {
onLike={onLike} onLike={onLike}
onStar={onStar} onStar={onStar}
onLock={onLock} onLock={onLock}
onEdit={onEdit}
/> />
</div> </div>

View file

@ -6,14 +6,14 @@ import { makePersistable, isHydrated } from 'mobx-persist-store';
export class AuthStore { export class AuthStore {
token: string = ''; token: string = '';
user: IUser = EMPTY_USER; user: IUser = EMPTY_USER;
private isTesterInternal: boolean = false; isTesterInternal: boolean = false;
constructor() { constructor() {
makeAutoObservable(this); makeAutoObservable(this);
void makePersistable(this, { void makePersistable(this, {
name: `vault48_auth_${process.env.REACT_APP_API_URL}`, name: `vault48_auth_${process.env.REACT_APP_API_URL}`,
properties: ['token', 'user'], properties: ['token', 'user', 'isTesterInternal'],
storage: window.localStorage, storage: window.localStorage,
}); });
} }

View file

@ -164,8 +164,9 @@
flex: 0 1 $width; flex: 0 1 $width;
max-width: 100vw; max-width: 100vw;
position: relative; position: relative;
background: transparentize($content_bg, 0.4); background: transparentize($content_bg, 0.1);
box-shadow: transparentize(white, 0.95) -1px 0; box-shadow: transparentize(white, 0.95) -1px 0;
border-radius: $radius 0 0 $radius;
} }
@mixin editor_round_button { @mixin editor_round_button {