[WEB-1899] fix: issue attachment delete modal and code refactor (#5085)
* chore: issue attachment modal state updated in store * fix: issue attachment delete modal fix and code refactor
This commit is contained in:
parent
6b12c78cea
commit
676ec7e396
5 changed files with 59 additions and 54 deletions
|
|
@ -52,7 +52,7 @@ export const IssueAttachmentsDetail: FC<TIssueAttachmentsDetail> = observer((pro
|
|||
isOpen={isDeleteIssueAttachmentModalOpen}
|
||||
onClose={() => setIsDeleteIssueAttachmentModalOpen(false)}
|
||||
handleAttachmentOperations={handleAttachmentOperations}
|
||||
data={attachment}
|
||||
attachmentId={attachmentId}
|
||||
/>
|
||||
)}
|
||||
<div className="flex h-[60px] items-center justify-between gap-1 rounded-md border-[2px] border-custom-border-200 bg-custom-background-100 px-4 py-2 text-sm">
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { useInstance, useIssueDetail } from "@/hooks/store";
|
|||
// components
|
||||
import { IssueAttachmentsListItem } from "./attachment-list-item";
|
||||
// types
|
||||
import { IssueAttachmentDeleteModal } from "./delete-attachment-modal";
|
||||
import { TAttachmentOperations } from "./root";
|
||||
|
||||
type TAttachmentOperationsRemoveModal = Exclude<TAttachmentOperations, "create">;
|
||||
|
|
@ -28,6 +29,8 @@ export const IssueAttachmentItemList: FC<TIssueAttachmentItemList> = observer((p
|
|||
const { config } = useInstance();
|
||||
const {
|
||||
attachment: { getAttachmentsByIssueId },
|
||||
attachmentDeleteModalId,
|
||||
toggleDeleteAttachmentModal,
|
||||
} = useIssueDetail();
|
||||
// derived values
|
||||
const issueAttachments = getAttachmentsByIssueId(issueId);
|
||||
|
|
@ -65,29 +68,34 @@ export const IssueAttachmentItemList: FC<TIssueAttachmentItemList> = observer((p
|
|||
if (!issueAttachments) return <></>;
|
||||
|
||||
return (
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className={`relative flex flex-col ${isDragActive && issueAttachments.length < 3 ? "min-h-[200px]" : ""} ${disabled ? "cursor-not-allowed" : "cursor-pointer"}`}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
{isDragActive && (
|
||||
<div className="absolute flex items-center justify-center left-0 top-0 h-full w-full bg-custom-background-90/75 z-30 ">
|
||||
<div className="flex items-center justify-center p-1 rounded-md bg-custom-background-100">
|
||||
<div className="flex flex-col justify-center items-center px-5 py-6 rounded-md border border-dashed border-custom-border-300">
|
||||
<UploadCloud className="size-7" />
|
||||
<span className="text-sm text-custom-text-300">Drag and drop anywhere to upload</span>
|
||||
<>
|
||||
{attachmentDeleteModalId && (
|
||||
<IssueAttachmentDeleteModal
|
||||
isOpen={Boolean(attachmentDeleteModalId)}
|
||||
onClose={() => toggleDeleteAttachmentModal(null)}
|
||||
handleAttachmentOperations={handleAttachmentOperations}
|
||||
attachmentId={attachmentDeleteModalId}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className={`relative flex flex-col ${isDragActive && issueAttachments.length < 3 ? "min-h-[200px]" : ""} ${disabled ? "cursor-not-allowed" : "cursor-pointer"}`}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
{isDragActive && (
|
||||
<div className="absolute flex items-center justify-center left-0 top-0 h-full w-full bg-custom-background-90/75 z-30 ">
|
||||
<div className="flex items-center justify-center p-1 rounded-md bg-custom-background-100">
|
||||
<div className="flex flex-col justify-center items-center px-5 py-6 rounded-md border border-dashed border-custom-border-300">
|
||||
<UploadCloud className="size-7" />
|
||||
<span className="text-sm text-custom-text-300">Drag and drop anywhere to upload</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{issueAttachments?.map((attachmentId) => (
|
||||
<IssueAttachmentsListItem
|
||||
key={attachmentId}
|
||||
attachmentId={attachmentId}
|
||||
disabled={disabled}
|
||||
handleAttachmentOperations={handleAttachmentOperations}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{issueAttachments?.map((attachmentId) => (
|
||||
<IssueAttachmentsListItem key={attachmentId} attachmentId={attachmentId} disabled={disabled} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,32 +8,25 @@ import { CustomMenu, Tooltip } from "@plane/ui";
|
|||
// components
|
||||
import { ButtonAvatars } from "@/components/dropdowns/member/avatar";
|
||||
import { getFileIcon } from "@/components/icons";
|
||||
import { IssueAttachmentDeleteModal } from "@/components/issues";
|
||||
// helpers
|
||||
import { convertBytesToSize, getFileExtension, getFileName } from "@/helpers/attachment.helper";
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
// hooks
|
||||
import { useIssueDetail, useMember } from "@/hooks/store";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// types
|
||||
import { TAttachmentOperations } from "./root";
|
||||
|
||||
type TAttachmentOperationsRemoveModal = Exclude<TAttachmentOperations, "create">;
|
||||
|
||||
type TIssueAttachmentsListItem = {
|
||||
attachmentId: string;
|
||||
handleAttachmentOperations: TAttachmentOperationsRemoveModal;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export const IssueAttachmentsListItem: FC<TIssueAttachmentsListItem> = observer((props) => {
|
||||
// props
|
||||
const { attachmentId, handleAttachmentOperations, disabled } = props;
|
||||
const { attachmentId, disabled } = props;
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
const {
|
||||
attachment: { getAttachmentById },
|
||||
isDeleteAttachmentModalOpen,
|
||||
toggleDeleteAttachmentModal,
|
||||
} = useIssueDetail();
|
||||
|
||||
|
|
@ -46,14 +39,6 @@ export const IssueAttachmentsListItem: FC<TIssueAttachmentsListItem> = observer(
|
|||
|
||||
return (
|
||||
<>
|
||||
{isDeleteAttachmentModalOpen && (
|
||||
<IssueAttachmentDeleteModal
|
||||
isOpen={isDeleteAttachmentModalOpen}
|
||||
onClose={() => toggleDeleteAttachmentModal(false)}
|
||||
handleAttachmentOperations={handleAttachmentOperations}
|
||||
data={attachment}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
|
|
@ -95,7 +80,7 @@ export const IssueAttachmentsListItem: FC<TIssueAttachmentsListItem> = observer(
|
|||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleDeleteAttachmentModal(true);
|
||||
toggleDeleteAttachmentModal(attachmentId);
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { FC, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// types
|
||||
import type { TIssueAttachment } from "@plane/types";
|
||||
// ui
|
||||
import { AlertModalCore } from "@plane/ui";
|
||||
// helper
|
||||
import { getFileName } from "@/helpers/attachment.helper";
|
||||
// hooks
|
||||
import { useIssueDetail } from "@/hooks/store";
|
||||
// types
|
||||
import { TAttachmentOperations } from "./root";
|
||||
|
||||
|
|
@ -13,15 +15,24 @@ export type TAttachmentOperationsRemoveModal = Exclude<TAttachmentOperations, "c
|
|||
type Props = {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
data: TIssueAttachment;
|
||||
attachmentId: string;
|
||||
handleAttachmentOperations: TAttachmentOperationsRemoveModal;
|
||||
};
|
||||
|
||||
export const IssueAttachmentDeleteModal: FC<Props> = (props) => {
|
||||
const { isOpen, onClose, data, handleAttachmentOperations } = props;
|
||||
export const IssueAttachmentDeleteModal: FC<Props> = observer((props) => {
|
||||
const { isOpen, onClose, attachmentId, handleAttachmentOperations } = props;
|
||||
// states
|
||||
const [loader, setLoader] = useState(false);
|
||||
|
||||
// store hooks
|
||||
const {
|
||||
attachment: { getAttachmentById },
|
||||
} = useIssueDetail();
|
||||
|
||||
// derived values
|
||||
const attachment = attachmentId ? getAttachmentById(attachmentId) : undefined;
|
||||
|
||||
// handlers
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
setLoader(false);
|
||||
|
|
@ -32,20 +43,21 @@ export const IssueAttachmentDeleteModal: FC<Props> = (props) => {
|
|||
handleAttachmentOperations.remove(assetId).finally(() => handleClose());
|
||||
};
|
||||
|
||||
if (!attachment) return <></>;
|
||||
return (
|
||||
<AlertModalCore
|
||||
handleClose={handleClose}
|
||||
handleSubmit={() => handleDeletion(data.id)}
|
||||
handleSubmit={() => handleDeletion(attachment.id)}
|
||||
isSubmitting={loader}
|
||||
isOpen={isOpen}
|
||||
title="Delete attachment"
|
||||
content={
|
||||
<>
|
||||
Are you sure you want to delete attachment-{" "}
|
||||
<span className="font-bold">{getFileName(data.attributes.name)}</span>? This attachment will be permanently
|
||||
removed. This action cannot be undone.
|
||||
<span className="font-bold">{getFileName(attachment.attributes.name)}</span>? This attachment will be
|
||||
permanently removed. This action cannot be undone.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export interface IIssueDetail
|
|||
isArchiveIssueModalOpen: string | null;
|
||||
isRelationModalOpen: TIssueRelationModal | null;
|
||||
isSubIssuesModalOpen: string | null;
|
||||
isDeleteAttachmentModalOpen: boolean;
|
||||
attachmentDeleteModalId: string | null;
|
||||
// computed
|
||||
isAnyModalOpen: boolean;
|
||||
// helper actions
|
||||
|
|
@ -71,7 +71,7 @@ export interface IIssueDetail
|
|||
toggleArchiveIssueModal: (value: string | null) => void;
|
||||
toggleRelationModal: (issueId: string | null, relationType: TIssueRelationTypes | null) => void;
|
||||
toggleSubIssuesModal: (value: string | null) => void;
|
||||
toggleDeleteAttachmentModal: (value:boolean) => void;
|
||||
toggleDeleteAttachmentModal: (attachmentId: string | null) => void;
|
||||
// store
|
||||
rootIssueStore: IIssueRootStore;
|
||||
issue: IIssueStore;
|
||||
|
|
@ -96,7 +96,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
isArchiveIssueModalOpen: string | null = null;
|
||||
isRelationModalOpen: TIssueRelationModal | null = null;
|
||||
isSubIssuesModalOpen: string | null = null;
|
||||
isDeleteAttachmentModalOpen: boolean = false;
|
||||
attachmentDeleteModalId: string | null = null;
|
||||
// store
|
||||
rootIssueStore: IIssueRootStore;
|
||||
issue: IIssueStore;
|
||||
|
|
@ -121,7 +121,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
isArchiveIssueModalOpen: observable.ref,
|
||||
isRelationModalOpen: observable.ref,
|
||||
isSubIssuesModalOpen: observable.ref,
|
||||
isDeleteAttachmentModalOpen: observable,
|
||||
attachmentDeleteModalId: observable.ref,
|
||||
// computed
|
||||
isAnyModalOpen: computed,
|
||||
// action
|
||||
|
|
@ -160,7 +160,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
!!this.isArchiveIssueModalOpen ||
|
||||
!!this.isRelationModalOpen?.issueId ||
|
||||
!!this.isSubIssuesModalOpen ||
|
||||
this.isDeleteAttachmentModalOpen
|
||||
!!this.attachmentDeleteModalId
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
toggleRelationModal = (issueId: string | null, relationType: TIssueRelationTypes | null) =>
|
||||
(this.isRelationModalOpen = { issueId, relationType });
|
||||
toggleSubIssuesModal = (issueId: string | null) => (this.isSubIssuesModalOpen = issueId);
|
||||
toggleDeleteAttachmentModal = (value: boolean) => (this.isDeleteAttachmentModalOpen = value);
|
||||
toggleDeleteAttachmentModal = (attachmentId: string | null) => (this.attachmentDeleteModalId = attachmentId);
|
||||
|
||||
// issue
|
||||
fetchIssue = async (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue