mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-16 17:51:43 +10:00
fix(client): 🐛 do not allow private resumes to be viewable or downloadable through the link
This commit is contained in:
@ -15,7 +15,7 @@
|
||||
.controller {
|
||||
@apply z-20 flex items-center justify-center shadow-lg;
|
||||
@apply flex rounded-l-full rounded-r-full px-4;
|
||||
@apply bg-neutral-50 dark:bg-neutral-800;
|
||||
@apply bg-zinc-50 dark:bg-zinc-900;
|
||||
@apply opacity-70 transition-opacity duration-200 hover:opacity-100;
|
||||
|
||||
> button {
|
||||
@ -23,6 +23,6 @@
|
||||
}
|
||||
|
||||
> hr {
|
||||
@apply mx-3 h-5 w-0.5 bg-neutral-900/40 dark:bg-neutral-50/20;
|
||||
@apply mx-3 h-5 w-0.5 bg-zinc-900/40 dark:bg-zinc-50/20;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ import {
|
||||
ZoomOut,
|
||||
} from '@mui/icons-material';
|
||||
import { ButtonBase, Divider, Tooltip, useMediaQuery, useTheme } from '@mui/material';
|
||||
import clsx from 'clsx';
|
||||
import dayjs from 'dayjs';
|
||||
import get from 'lodash/get';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@ -26,6 +25,7 @@ import { printResumeAsPdf, PrintResumeAsPdfParams } from '@/services/printer';
|
||||
import { togglePageBreakLine, togglePageOrientation, toggleSidebar } from '@/store/build/buildSlice';
|
||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||
import getResumeUrl from '@/utils/getResumeUrl';
|
||||
import { cn } from '@/utils/styles';
|
||||
|
||||
import styles from './ArtboardController.module.scss';
|
||||
|
||||
@ -60,7 +60,7 @@ const ArtboardController: React.FC<ReactZoomPanPinchHandlers> = ({ zoomIn, zoomO
|
||||
const url = getResumeUrl(resume, { withHost: true });
|
||||
await navigator.clipboard.writeText(url);
|
||||
|
||||
toast.success(t<string>('common.toast.success.resume-link-copied'));
|
||||
toast.success(t('common.toast.success.resume-link-copied'));
|
||||
};
|
||||
|
||||
const handleExportPDF = async () => {
|
||||
@ -77,40 +77,40 @@ const ArtboardController: React.FC<ReactZoomPanPinchHandlers> = ({ zoomIn, zoomO
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx({
|
||||
className={cn({
|
||||
[styles.container]: true,
|
||||
[styles.pushLeft]: left.open,
|
||||
[styles.pushRight]: right.open,
|
||||
})}
|
||||
>
|
||||
<div className={styles.controller}>
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.undo')}>
|
||||
<ButtonBase onClick={handleUndo} className={clsx({ 'pointer-events-none opacity-50': past.length < 2 })}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.undo')}>
|
||||
<ButtonBase onClick={handleUndo} className={cn({ 'pointer-events-none opacity-50': past.length < 2 })}>
|
||||
<UndoOutlined fontSize="medium" />
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.redo')}>
|
||||
<ButtonBase onClick={handleRedo} className={clsx({ 'pointer-events-none opacity-50': future.length === 0 })}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.redo')}>
|
||||
<ButtonBase onClick={handleRedo} className={cn({ 'pointer-events-none opacity-50': future.length === 0 })}>
|
||||
<RedoOutlined fontSize="medium" />
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.zoom-in')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.zoom-in')}>
|
||||
<ButtonBase onClick={() => zoomIn(0.25)}>
|
||||
<ZoomIn fontSize="medium" />
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.zoom-out')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.zoom-out')}>
|
||||
<ButtonBase onClick={() => zoomOut(0.25)}>
|
||||
<ZoomOut fontSize="medium" />
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.center-artboard')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.center-artboard')}>
|
||||
<ButtonBase onClick={() => centerView(0.95)}>
|
||||
<FilterCenterFocus fontSize="medium" />
|
||||
</ButtonBase>
|
||||
@ -120,10 +120,10 @@ const ArtboardController: React.FC<ReactZoomPanPinchHandlers> = ({ zoomIn, zoomO
|
||||
|
||||
{isDesktop && (
|
||||
<>
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.toggle-orientation')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.toggle-orientation')}>
|
||||
<ButtonBase
|
||||
onClick={handleTogglePageOrientation}
|
||||
className={clsx({ 'pointer-events-none opacity-50': pages.length === 1 })}
|
||||
className={cn({ 'pointer-events-none opacity-50': pages.length === 1 })}
|
||||
>
|
||||
{orientation === 'vertical' ? (
|
||||
<AlignHorizontalCenter fontSize="medium" />
|
||||
@ -133,13 +133,13 @@ const ArtboardController: React.FC<ReactZoomPanPinchHandlers> = ({ zoomIn, zoomO
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.toggle-page-break-line')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.toggle-page-break-line')}>
|
||||
<ButtonBase onClick={handleTogglePageBreakLine}>
|
||||
<InsertPageBreak fontSize="medium" />
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.toggle-sidebars')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.toggle-sidebars')}>
|
||||
<ButtonBase onClick={handleToggleSidebar}>
|
||||
<ViewSidebar fontSize="medium" />
|
||||
</ButtonBase>
|
||||
@ -149,13 +149,13 @@ const ArtboardController: React.FC<ReactZoomPanPinchHandlers> = ({ zoomIn, zoomO
|
||||
</>
|
||||
)}
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.copy-link')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.copy-link')}>
|
||||
<ButtonBase onClick={handleCopyLink}>
|
||||
<Link fontSize="medium" />
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip arrow placement="top" title={t<string>('builder.controller.tooltip.export-pdf')}>
|
||||
<Tooltip arrow placement="top" title={t('builder.controller.tooltip.export-pdf')}>
|
||||
<ButtonBase onClick={handleExportPDF} disabled={isLoading}>
|
||||
<Download fontSize="medium" />
|
||||
</ButtonBase>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.center {
|
||||
@apply mx-0 flex flex-grow pt-12 lg:pt-16;
|
||||
@apply transition-[margin-left,margin-right] duration-200;
|
||||
@apply bg-neutral-200 dark:bg-neutral-900;
|
||||
@apply bg-zinc-100 dark:bg-zinc-900;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import { TransformComponent, TransformWrapper } from 'react-zoom-pan-pinch';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
import { cn } from '@/utils/styles';
|
||||
|
||||
import ArtboardController from './ArtboardController';
|
||||
import styles from './Center.module.scss';
|
||||
@ -19,7 +19,7 @@ const Center = () => {
|
||||
if (isEmpty(resume)) return null;
|
||||
|
||||
return (
|
||||
<div className={clsx(styles.center)}>
|
||||
<div className={cn(styles.center)}>
|
||||
<Header />
|
||||
|
||||
<TransformWrapper
|
||||
@ -35,7 +35,7 @@ const Center = () => {
|
||||
<>
|
||||
<TransformComponent wrapperClass={styles.wrapper}>
|
||||
<div
|
||||
className={clsx({
|
||||
className={cn({
|
||||
[styles.artboard]: true,
|
||||
'flex-col': orientation === 'vertical',
|
||||
})}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
.header {
|
||||
@apply mx-0 flex justify-between shadow;
|
||||
@apply bg-neutral-800 text-neutral-100;
|
||||
@apply bg-zinc-900 text-zinc-100;
|
||||
@apply transition-[margin-left,margin-right] duration-200;
|
||||
|
||||
button > svg {
|
||||
@apply text-base text-neutral-100;
|
||||
@apply text-base text-zinc-100;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ import {
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@ -37,6 +36,7 @@ import { setSidebarState, toggleSidebar } from '@/store/build/buildSlice';
|
||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||
import { setModalState } from '@/store/modal/modalSlice';
|
||||
import getResumeUrl from '@/utils/getResumeUrl';
|
||||
import { cn } from '@/utils/styles';
|
||||
|
||||
import styles from './Header.module.scss';
|
||||
|
||||
@ -102,7 +102,7 @@ const Header = () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
@ -132,14 +132,14 @@ const Header = () => {
|
||||
const url = getResumeUrl(resume, { withHost: true });
|
||||
await navigator.clipboard.writeText(url);
|
||||
|
||||
toast.success(t<string>('common.toast.success.resume-link-copied'));
|
||||
toast.success(t('common.toast.success.resume-link-copied'));
|
||||
};
|
||||
|
||||
return (
|
||||
<AppBar elevation={0} position="fixed">
|
||||
<Toolbar
|
||||
variant="regular"
|
||||
className={clsx({
|
||||
className={cn({
|
||||
[styles.header]: true,
|
||||
[styles.pushLeft]: left.open,
|
||||
[styles.pushRight]: right.open,
|
||||
@ -165,14 +165,14 @@ const Header = () => {
|
||||
<ListItemIcon>
|
||||
<DriveFileRenameOutline className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.header.menu.rename')}</ListItemText>
|
||||
<ListItemText>{t('builder.header.menu.rename')}</ListItemText>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onClick={handleDuplicate}>
|
||||
<ListItemIcon>
|
||||
<CopyAll className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.header.menu.duplicate')}</ListItemText>
|
||||
<ListItemText>{t('builder.header.menu.duplicate')}</ListItemText>
|
||||
</MenuItem>
|
||||
|
||||
{resume.public ? (
|
||||
@ -180,27 +180,27 @@ const Header = () => {
|
||||
<ListItemIcon>
|
||||
<LinkIcon className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.header.menu.share-link')}</ListItemText>
|
||||
<ListItemText>{t('builder.header.menu.share-link')}</ListItemText>
|
||||
</MenuItem>
|
||||
) : (
|
||||
<Tooltip arrow placement="right" title={t<string>('builder.header.menu.tooltips.share-link')}>
|
||||
<Tooltip arrow placement="right" title={t('builder.header.menu.tooltips.share-link')}>
|
||||
<div>
|
||||
<MenuItem>
|
||||
<ListItemIcon>
|
||||
<LinkIcon className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.header.menu.share-link')}</ListItemText>
|
||||
<ListItemText>{t('builder.header.menu.share-link')}</ListItemText>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
<Tooltip arrow placement="right" title={t<string>('builder.header.menu.tooltips.delete')}>
|
||||
<Tooltip arrow placement="right" title={t('builder.header.menu.tooltips.delete')}>
|
||||
<MenuItem onClick={handleDelete}>
|
||||
<ListItemIcon>
|
||||
<Delete className="scale-90" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t<string>('builder.header.menu.delete')}</ListItemText>
|
||||
<ListItemText>{t('builder.header.menu.delete')}</ListItemText>
|
||||
</MenuItem>
|
||||
</Tooltip>
|
||||
</Menu>
|
||||
|
||||
@ -18,8 +18,8 @@
|
||||
content: 'Page Break';
|
||||
top: calc(297mm - 19px);
|
||||
|
||||
@apply absolute w-full border-b border-dashed border-neutral-800/75;
|
||||
@apply flex items-end justify-end pr-2 pb-0.5 text-xs font-bold text-neutral-800/75;
|
||||
@apply absolute w-full border-b border-dashed border-zinc-900/75;
|
||||
@apply flex items-end justify-end pr-2 pb-0.5 text-xs font-bold text-zinc-900/75;
|
||||
@apply print:hidden;
|
||||
|
||||
:global(.preview-mode) &,
|
||||
|
||||
@ -49,9 +49,7 @@ const Page: React.FC<Props> = ({ page, showPageNumbers = false }) => {
|
||||
{TemplatePage && <TemplatePage page={page} />}
|
||||
</div>
|
||||
|
||||
{showPageNumbers && (
|
||||
<h4 className={styles.pageNumber}>{`${t<string>('builder.common.glossary.page')} ${page + 1}`}</h4>
|
||||
)}
|
||||
{showPageNumbers && <h4 className={styles.pageNumber}>{`${t('builder.common.glossary.page')} ${page + 1}`}</h4>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user