chore: remove memo card dialog (#475)

This commit is contained in:
boojack 2022-11-15 21:16:53 +08:00 committed by GitHub
parent 67195859dc
commit de2eff474c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 3 additions and 322 deletions

View File

@ -11,7 +11,6 @@ import Icon from "./Icon";
import toastHelper from "./Toast";
import MemoContent from "./MemoContent";
import MemoResources from "./MemoResources";
import showMemoCardDialog from "./MemoCardDialog";
import showShareMemoImageDialog from "./ShareMemoImageDialog";
import showPreviewImageDialog from "./PreviewImageDialog";
import "../less/memo.less";
@ -51,14 +50,6 @@ const Memo: React.FC<Props> = (props: Props) => {
};
}, [i18n.language]);
const handleShowMemoStoryDialog = () => {
if (isVisitorMode) {
return;
}
showMemoCardDialog(memo);
};
const handleViewMemoDetailPage = () => {
navigate(`/m/${memo.id}`);
};
@ -116,7 +107,7 @@ const Memo: React.FC<Props> = (props: Props) => {
const memoTemp = await memoService.getMemoById(Number(memoId) ?? UNKNOWN_ID);
if (memoTemp) {
showMemoCardDialog(memoTemp);
navigate(`/m/${memoTemp.id}`);
} else {
toastHelper.error(t("message.memo-not-found"));
targetEl.classList.remove("memo-link-text");
@ -209,9 +200,7 @@ const Memo: React.FC<Props> = (props: Props) => {
{memo.pinned && <div className="corner-container"></div>}
<div className="memo-top-wrapper">
<div className="status-text-container">
<span className="time-text" onClick={handleShowMemoStoryDialog}>
{displayTimeStr}
</span>
<span className="time-text">{displayTimeStr}</span>
{memo.visibility !== "PRIVATE" && !isVisitorMode && (
<span
className={`status-text ${memo.visibility.toLocaleLowerCase()}`}

View File

@ -1,225 +0,0 @@
import copy from "copy-to-clipboard";
import { useState, useEffect, useCallback } from "react";
import { useTranslation } from "react-i18next";
import { editorStateService, memoService, userService } from "../services";
import { useAppSelector } from "../store";
import { UNKNOWN_ID } from "../helpers/consts";
import * as utils from "../helpers/utils";
import { parseHTMLToRawText } from "../helpers/utils";
import { marked } from "../labs/marked";
import { MARK_REG } from "../labs/marked/parser";
import toastHelper from "./Toast";
import { generateDialog } from "./Dialog";
import Icon from "./Icon";
import MemoContent from "./MemoContent";
import MemoResources from "./MemoResources";
import showChangeMemoCreatedTsDialog from "./ChangeMemoCreatedTsDialog";
import "../less/memo-card-dialog.less";
interface LinkedMemo extends Memo {
createdAtStr: string;
dateStr: string;
}
interface Props extends DialogProps {
memo: Memo;
}
const MemoCardDialog: React.FC<Props> = (props: Props) => {
const { t } = useTranslation();
const memos = useAppSelector((state) => state.memo.memos);
const [memo, setMemo] = useState<Memo>({
...props.memo,
});
const [linkMemos, setLinkMemos] = useState<LinkedMemo[]>([]);
const [linkedMemos, setLinkedMemos] = useState<LinkedMemo[]>([]);
const isVisitorMode = userService.isVisitorMode();
useEffect(() => {
const fetchLinkedMemos = async () => {
try {
const linkMemos: LinkedMemo[] = [];
const matchedArr = [...memo.content.matchAll(MARK_REG)];
for (const matchRes of matchedArr) {
if (matchRes && matchRes.length === 3) {
const id = Number(matchRes[2]);
if (id === memo.id) {
continue;
}
const memoTemp = await memoService.getMemoById(id);
if (memoTemp) {
linkMemos.push({
...memoTemp,
createdAtStr: utils.getDateTimeString(memoTemp.displayTs),
dateStr: utils.getDateString(memoTemp.displayTs),
});
}
}
}
setLinkMemos([...linkMemos]);
const linkedMemos = await memoService.getLinkedMemos(memo.id);
setLinkedMemos(
linkedMemos
.filter((m) => m.rowStatus === "NORMAL" && m.id !== memo.id)
.sort((a, b) => utils.getTimeStampByDate(b.displayTs) - utils.getTimeStampByDate(a.displayTs))
.map((m) => ({
...m,
createdAtStr: utils.getDateTimeString(m.displayTs),
dateStr: utils.getDateString(m.displayTs),
}))
);
} catch (error) {
// do nth
}
};
fetchLinkedMemos();
memoService.getMemoById(memo.id).then((memo) => {
setMemo(memo);
});
}, [memos, memo.id]);
const handleMemoCreatedAtClick = () => {
if (isVisitorMode) {
return;
}
showChangeMemoCreatedTsDialog(memo.id);
};
const handleMemoContentClick = useCallback(async (e: React.MouseEvent) => {
const targetEl = e.target as HTMLElement;
if (targetEl.className === "memo-link-text") {
const nextMemoId = targetEl.dataset?.value;
const memoTemp = await memoService.getMemoById(Number(nextMemoId) ?? UNKNOWN_ID);
if (memoTemp) {
const nextMemo = {
...memoTemp,
createdAtStr: utils.getDateTimeString(memoTemp.displayTs),
};
setLinkMemos([]);
setLinkedMemos([]);
setMemo(nextMemo);
} else {
toastHelper.error(t("message.memo-not-found"));
targetEl.classList.remove("memo-link-text");
}
}
}, []);
const handleLinkedMemoClick = useCallback((memo: Memo) => {
setLinkMemos([]);
setLinkedMemos([]);
setMemo(memo);
}, []);
const handleGotoMemoLinkBtnClick = () => {
window.open(`/m/${memo.id}`);
};
const handleEditMemoBtnClick = () => {
props.destroy();
editorStateService.setEditMemoWithId(memo.id);
};
const handleCopyContent = () => {
copy(memo.content);
toastHelper.success(t("message.succeed-copy-content"));
};
return (
<>
<div className="memo-card-container">
<div className="header-container">
<p className="time-text" onClick={handleMemoCreatedAtClick}>
{utils.getDateTimeString(memo.displayTs)}
</p>
<div className="btns-container">
{!isVisitorMode && (
<>
<button className="btn edit-btn" onClick={handleGotoMemoLinkBtnClick}>
<Icon.ExternalLink className="icon-img" />
</button>
<button className="btn copy-btn" onClick={handleCopyContent}>
<Icon.Clipboard className="icon-img" />
</button>
<button className="btn edit-btn" onClick={handleEditMemoBtnClick}>
<Icon.Edit3 className="icon-img" />
</button>
<span className="split-line">/</span>
</>
)}
<button className="btn close-btn" onClick={props.destroy}>
<Icon.X className="icon-img" />
</button>
</div>
</div>
<div className="memo-container">
<MemoContent displayConfig={{ enableExpand: false }} content={memo.content} onMemoContentClick={handleMemoContentClick} />
<MemoResources resourceList={memo.resourceList} />
</div>
<div className="layer-container"></div>
{linkMemos.map((_, idx) => {
if (idx < 4) {
return (
<div
className="background-layer-container"
key={idx}
style={{
bottom: (idx + 1) * -3 + "px",
left: (idx + 1) * 5 + "px",
width: `calc(100% - ${(idx + 1) * 10}px)`,
zIndex: -idx - 1,
}}
></div>
);
} else {
return null;
}
})}
</div>
{linkMemos.length > 0 ? (
<div className="linked-memos-wrapper">
<p className="normal-text">{linkMemos.length} related MEMO</p>
{linkMemos.map((memo, index) => {
const rawtext = parseHTMLToRawText(marked(memo.content)).replaceAll("\n", " ");
return (
<div className="linked-memo-container" key={`${index}-${memo.id}`} onClick={() => handleLinkedMemoClick(memo)}>
<span className="time-text">{memo.dateStr} </span>
{rawtext}
</div>
);
})}
</div>
) : null}
{linkedMemos.length > 0 ? (
<div className="linked-memos-wrapper">
<p className="normal-text">{linkedMemos.length} linked MEMO</p>
{linkedMemos.map((memo, index) => {
const rawtext = parseHTMLToRawText(marked(memo.content)).replaceAll("\n", " ");
return (
<div className="linked-memo-container" key={`${index}-${memo.id}`} onClick={() => handleLinkedMemoClick(memo)}>
<span className="time-text">{memo.dateStr} </span>
{rawtext}
</div>
);
})}
</div>
) : null}
</>
);
};
export default function showMemoCardDialog(memo: Memo): void {
generateDialog(
{
className: "memo-card-dialog",
},
MemoCardDialog,
{ memo }
);
}

View File

@ -1,83 +0,0 @@
.dialog-wrapper.memo-card-dialog {
@apply px-4;
> .dialog-container {
@apply w-full p-0 bg-transparent flex flex-col justify-start items-center;
> .memo-card-container {
@apply flex flex-col justify-start items-start relative w-128 max-w-full py-3 px-6 mb-3 rounded-lg bg-yellow-200;
> * {
z-index: 1;
}
> .header-container {
@apply flex flex-row justify-between items-center w-full h-auto pb-0 my-0;
> .time-text {
@apply text-sm text-gray-500 font-mono;
}
> .btns-container {
@apply flex flex-row justify-end items-center;
> .btn {
@apply flex flex-row justify-center items-center w-6 h-6 p-1 ml-2 rounded text-gray-600 hover:bg-white;
}
> .split-line {
@apply font-mono text-gray-300 ml-2;
}
}
}
> .memo-container {
@apply w-full flex flex-col justify-start items-start pt-2;
}
> .normal-text {
@apply mt-2 text-sm text-gray-500;
}
> .layer-container,
> .background-layer-container {
@apply bg-white;
position: absolute;
bottom: -3px;
left: 3px;
width: calc(100% - 6px);
height: 100%;
border-radius: 8px;
z-index: -1;
border-bottom: 1px solid lightgray;
}
> .layer-container {
@apply bg-white;
z-index: 0;
border: 1px solid lightgray;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
}
> .linked-memos-wrapper {
@apply flex flex-col justify-start items-start w-128 max-w-full mt-2 py-3 px-6 rounded-lg bg-white last:mb-8;
> .normal-text {
@apply text-sm;
}
> .linked-memo-container {
@apply text-sm leading-6 mt-2 cursor-pointer max-w-full truncate hover:opacity-80;
> .time-text {
@apply font-mono text-gray-500;
}
}
}
}
}

View File

@ -28,7 +28,7 @@
@apply flex flex-row justify-start items-center;
> .time-text {
@apply text-xs text-gray-400 cursor-pointer;
@apply text-xs text-gray-400;
font-size: 13px;
}