edit logic
This commit is contained in:
parent
8f0b8c48a9
commit
aec66cdc2c
1
src/widgets/action-card/index.ts
Normal file
1
src/widgets/action-card/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default as ActionCard } from "./ui/ActionCard";
|
||||
138
src/widgets/action-card/ui/ActionCard.tsx
Normal file
138
src/widgets/action-card/ui/ActionCard.tsx
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
import type { Chain } from "@/entities/chain/schema";
|
||||
import type { Action } from "@/entities/action/schema";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { ChangeWaitForButton } from "@/features/change-wait-for";
|
||||
import { getActionAttachmentType } from "@/entities/action/lib";
|
||||
|
||||
import { IconButton } from "@mui/material";
|
||||
import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
|
||||
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
|
||||
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
|
||||
import { Menu, MenuItem, Divider } from "@mui/material";
|
||||
|
||||
interface ActionCardProps {
|
||||
chain: Chain;
|
||||
action: Action;
|
||||
actionIndex: number;
|
||||
onEdit?: (actionIndex: number) => void;
|
||||
}
|
||||
|
||||
export default function ActionCard({
|
||||
chain,
|
||||
action,
|
||||
actionIndex,
|
||||
onEdit,
|
||||
}: ActionCardProps) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
|
||||
if (action.actionType === "comment") {
|
||||
const attachmentType = getActionAttachmentType(action);
|
||||
|
||||
return (
|
||||
<div className="relative w-[450px] select-none whitespace-pre-line rounded-md bg-white text-[#4C4E64DE] opacity-[84%] shadow-lg after:absolute after:-bottom-12 after:left-1/2 after:h-8 after:w-1 after:-translate-x-1/2 after:rounded-md after:bg-[#666CFF] after:opacity-[12%]">
|
||||
<div className="absolute -right-3 top-0 translate-x-full">
|
||||
<IconButton
|
||||
onClick={(event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
setIsOpen(true);
|
||||
}}
|
||||
sx={{
|
||||
borderRadius: "4px",
|
||||
border: "1px solid #4C4E641F",
|
||||
width: "32px",
|
||||
height: "32px",
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<MoreHorizIcon />
|
||||
</IconButton>
|
||||
|
||||
<Menu
|
||||
className="mt-2"
|
||||
anchorEl={anchorEl}
|
||||
open={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
if (onEdit) onEdit(actionIndex);
|
||||
}}
|
||||
>
|
||||
<EditIcon
|
||||
sx={{ color: "#4C4E64DE", opacity: "87%" }}
|
||||
className="mr-2"
|
||||
/>
|
||||
<span className="font-normal text-[#4C4E64DE] opacity-[87%]">
|
||||
Редактировать
|
||||
</span>
|
||||
</MenuItem>
|
||||
|
||||
<Divider sx={{ my: 0.5 }} />
|
||||
|
||||
<MenuItem>
|
||||
<ArrowUpwardIcon
|
||||
sx={{ color: "#4C4E64DE", opacity: "87%" }}
|
||||
className="mr-2"
|
||||
/>
|
||||
<span className="font-normal text-[#4C4E64DE] opacity-[87%]">
|
||||
Переместить выше
|
||||
</span>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem>
|
||||
<ArrowDownwardIcon
|
||||
sx={{ color: "#4C4E64DE", opacity: "87%" }}
|
||||
className="mr-2"
|
||||
/>
|
||||
<span className="font-normal text-[#4C4E64DE] opacity-[87%]">
|
||||
Переместить ниже
|
||||
</span>
|
||||
</MenuItem>
|
||||
|
||||
<Divider sx={{ my: 0.5 }} />
|
||||
|
||||
<MenuItem>
|
||||
<DeleteOutlineIcon
|
||||
sx={{ color: "#4C4E64DE", opacity: "87%" }}
|
||||
className="mr-2"
|
||||
/>
|
||||
<span className="font-normal text-[#4C4E64DE] opacity-[87%]">
|
||||
Удалить
|
||||
</span>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
{attachmentType === "image" && (
|
||||
<img
|
||||
src={action.fileUrls[0]}
|
||||
alt="Image"
|
||||
draggable={false}
|
||||
className={`w-full select-none ${!action.text && "rounded-b-md"} rounded-t-md`}
|
||||
/>
|
||||
)}
|
||||
{action.text && <div className="p-4">{action.text}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative flex select-none items-center gap-x-2 text-[#4C4E64DE] opacity-[84%] before:absolute before:-top-6 before:left-1/2 before:h-4 before:w-4 before:-translate-x-1/2 before:rounded-full before:border-[2.5px] before:border-primary after:absolute after:left-1/2 after:top-11 after:h-16 after:w-1 after:-translate-x-1/2 after:rounded-md after:bg-[#666CFF] after:opacity-[12%]">
|
||||
<span>
|
||||
Задержка: {humanizeDuration(action.waitFor * 1000, { language: "ru" })}
|
||||
</span>
|
||||
|
||||
<ChangeWaitForButton
|
||||
chainId={chain._id!}
|
||||
actionIndex={actionIndex}
|
||||
action={action}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -2,19 +2,17 @@ import type { Chain } from "@/entities/chain/schema";
|
|||
import { useChainState } from "@/entities/chain/model";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
|
||||
import { getActionAttachmentType } from "@/entities/action/lib";
|
||||
|
||||
import { useState, useRef } from "react";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import { upsertChain } from "@/entities/chain/api/upsert";
|
||||
import { ChangeWaitForButton } from "@/features/change-wait-for";
|
||||
|
||||
import { ActionEditor } from "@/widgets/action-editor";
|
||||
import { ActionCard } from "@/widgets/action-card";
|
||||
import { RenameChainButton } from "@/features/rename-chain";
|
||||
import { DeleteChainButton } from "@/features/delete-chain";
|
||||
|
||||
import { Typography, Button } from "@mui/material";
|
||||
import Breadcrumbs from "@mui/material/Breadcrumbs";
|
||||
import { CommentAction } from "@/entities/action/schema";
|
||||
|
||||
interface ChainEditorProps {
|
||||
chain: Chain;
|
||||
|
|
@ -22,11 +20,16 @@ interface ChainEditorProps {
|
|||
|
||||
export default function ChainEditor({ chain }: ChainEditorProps) {
|
||||
const actionsListRef = useRef<HTMLDivElement>(null);
|
||||
const [addingNewAction, setAddingNewAction] = useState(false);
|
||||
const [addingNewAction, setAddingNewAction] = useState(
|
||||
!chain.actions || chain.actions.length === 0,
|
||||
);
|
||||
|
||||
const navigate = useNavigate({ from: "/$namespace/$chainId" });
|
||||
const addCommentAction = useChainState((state) => state.addCommentAction);
|
||||
const updateAction = useChainState((state) => state.updateAction);
|
||||
const [actionToEdit, setActionToEdit] = useState<number | null>(null);
|
||||
|
||||
if (!chain.actions || chain.actions.length === 0 || addingNewAction)
|
||||
if (!chain.actions || addingNewAction || actionToEdit !== null)
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="flex items-center justify-between">
|
||||
|
|
@ -55,11 +58,21 @@ export default function ChainEditor({ chain }: ChainEditorProps) {
|
|||
|
||||
<div className="flex grow flex-col items-center justify-center">
|
||||
<ActionEditor
|
||||
onSave={async (_, action) => {
|
||||
addCommentAction(chain._id!, action);
|
||||
await upsertChain(chain);
|
||||
initialAction={
|
||||
actionToEdit !== null
|
||||
? (chain.actions?.[actionToEdit] as CommentAction)
|
||||
: undefined
|
||||
}
|
||||
onSave={async (actionIndex, action) => {
|
||||
if (addingNewAction) {
|
||||
addCommentAction(chain._id!, action);
|
||||
setAddingNewAction(false);
|
||||
} else if (actionToEdit !== null) {
|
||||
updateAction(chain._id!, actionIndex, action);
|
||||
setActionToEdit(null);
|
||||
}
|
||||
|
||||
if (addingNewAction) setAddingNewAction(false);
|
||||
await upsertChain(chain);
|
||||
navigate({ to: "/$namespace/$chainId" });
|
||||
|
||||
setTimeout(
|
||||
|
|
@ -73,8 +86,9 @@ export default function ChainEditor({ chain }: ChainEditorProps) {
|
|||
}}
|
||||
onClose={() => {
|
||||
if (addingNewAction) setAddingNewAction(false);
|
||||
if (actionToEdit !== null) setActionToEdit(null);
|
||||
}}
|
||||
canExit={addingNewAction}
|
||||
canExit={chain.actions?.length !== 0}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -100,46 +114,15 @@ export default function ChainEditor({ chain }: ChainEditorProps) {
|
|||
ref={actionsListRef}
|
||||
className="no-scrollbar flex grow flex-col items-center gap-y-24 overflow-y-scroll pb-20 pt-8"
|
||||
>
|
||||
{chain.actions.map((action, index) => {
|
||||
if (action.actionType === "comment") {
|
||||
const attachmentType = getActionAttachmentType(action);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="relative w-[450px] select-none whitespace-pre-line rounded-md bg-white text-[#4C4E64DE] opacity-[84%] shadow-lg after:absolute after:-bottom-12 after:left-1/2 after:h-8 after:w-1 after:-translate-x-1/2 after:rounded-md after:bg-[#666CFF] after:opacity-[12%]"
|
||||
>
|
||||
{attachmentType === "image" && (
|
||||
<img
|
||||
src={action.fileUrls[0]}
|
||||
alt="Image"
|
||||
draggable={false}
|
||||
className={`w-full select-none ${!action.text && "rounded-b-md"} rounded-t-md`}
|
||||
/>
|
||||
)}
|
||||
{action.text && <div className="p-4">{action.text}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="relative flex select-none items-center gap-x-2 text-[#4C4E64DE] opacity-[84%] before:absolute before:-top-6 before:left-1/2 before:h-4 before:w-4 before:-translate-x-1/2 before:rounded-full before:border-[2.5px] before:border-primary after:absolute after:left-1/2 after:top-11 after:h-16 after:w-1 after:-translate-x-1/2 after:rounded-md after:bg-[#666CFF] after:opacity-[12%]"
|
||||
>
|
||||
<span>
|
||||
Задержка:{" "}
|
||||
{humanizeDuration(action.waitFor * 1000, { language: "ru" })}
|
||||
</span>
|
||||
|
||||
<ChangeWaitForButton
|
||||
chainId={chain._id!}
|
||||
actionIndex={index}
|
||||
action={action}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{chain.actions.map((action, index) => (
|
||||
<ActionCard
|
||||
key={index}
|
||||
chain={chain}
|
||||
action={action}
|
||||
actionIndex={index}
|
||||
onEdit={setActionToEdit}
|
||||
/>
|
||||
))}
|
||||
|
||||
<div className="-mt-4">
|
||||
<Button
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user