forked from github/plane
fix: edit/delete for draft issue (#2190)
* fix: edit/delete * fix: build issue * fix: draft issue modal opening in kanban card
This commit is contained in:
parent
eda4da8aed
commit
32d945be0d
@ -52,10 +52,22 @@ const issueViewOptions: { type: TIssueViewOptions; Icon: any }[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const issueViewForDraftIssues: { type: TIssueViewOptions; Icon: any }[] = [
|
||||||
|
{
|
||||||
|
type: "list",
|
||||||
|
Icon: FormatListBulletedOutlined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "kanban",
|
||||||
|
Icon: GridViewOutlined,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const IssuesFilterView: React.FC = () => {
|
export const IssuesFilterView: React.FC = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, viewId } = router.query;
|
const { workspaceSlug, projectId, viewId } = router.query;
|
||||||
const isArchivedIssues = router.pathname.includes("archived-issues");
|
const isArchivedIssues = router.pathname.includes("archived-issues");
|
||||||
|
const isDraftIssues = router.pathname.includes("draft-issues");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
displayFilters,
|
displayFilters,
|
||||||
@ -75,7 +87,7 @@ export const IssuesFilterView: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{!isArchivedIssues && (
|
{!isArchivedIssues && !isDraftIssues && (
|
||||||
<div className="flex items-center gap-x-1">
|
<div className="flex items-center gap-x-1">
|
||||||
{issueViewOptions.map((option) => (
|
{issueViewOptions.map((option) => (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@ -105,6 +117,36 @@ export const IssuesFilterView: React.FC = () => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isDraftIssues && (
|
||||||
|
<div className="flex items-center gap-x-1">
|
||||||
|
{issueViewForDraftIssues.map((option) => (
|
||||||
|
<Tooltip
|
||||||
|
key={option.type}
|
||||||
|
tooltipContent={
|
||||||
|
<span className="capitalize">{replaceUnderscoreIfSnakeCase(option.type)} View</span>
|
||||||
|
}
|
||||||
|
position="bottom"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`grid h-7 w-7 place-items-center rounded p-1 outline-none hover:bg-custom-sidebar-background-80 duration-300 ${
|
||||||
|
displayFilters.layout === option.type
|
||||||
|
? "bg-custom-sidebar-background-80"
|
||||||
|
: "text-custom-sidebar-text-200"
|
||||||
|
}`}
|
||||||
|
onClick={() => setDisplayFilters({ layout: option.type })}
|
||||||
|
>
|
||||||
|
<option.Icon
|
||||||
|
sx={{
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
className={option.type === "gantt_chart" ? "rotate-90" : ""}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<SelectFilters
|
<SelectFilters
|
||||||
filters={filters}
|
filters={filters}
|
||||||
onSelect={(option) => {
|
onSelect={(option) => {
|
||||||
|
@ -49,7 +49,8 @@ type Props = {
|
|||||||
};
|
};
|
||||||
secondaryButton?: React.ReactNode;
|
secondaryButton?: React.ReactNode;
|
||||||
};
|
};
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit" | "updateDraft") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
|
handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void;
|
||||||
handleOnDragEnd: (result: DropResult) => Promise<void>;
|
handleOnDragEnd: (result: DropResult) => Promise<void>;
|
||||||
openIssuesListModal: (() => void) | null;
|
openIssuesListModal: (() => void) | null;
|
||||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||||
@ -66,6 +67,7 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
dragDisabled = false,
|
dragDisabled = false,
|
||||||
emptyState,
|
emptyState,
|
||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
|
handleDraftIssueAction,
|
||||||
handleOnDragEnd,
|
handleOnDragEnd,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
@ -132,6 +134,7 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
states={states}
|
states={states}
|
||||||
addIssueToGroup={addIssueToGroup}
|
addIssueToGroup={addIssueToGroup}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
|
handleDraftIssueAction={handleDraftIssueAction}
|
||||||
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
||||||
removeIssue={removeIssue}
|
removeIssue={removeIssue}
|
||||||
myIssueProjectId={myIssueProjectId}
|
myIssueProjectId={myIssueProjectId}
|
||||||
@ -149,6 +152,7 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
disableAddIssueOption={disableAddIssueOption}
|
disableAddIssueOption={disableAddIssueOption}
|
||||||
dragDisabled={dragDisabled}
|
dragDisabled={dragDisabled}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
|
handleDraftIssueAction={handleDraftIssueAction}
|
||||||
handleTrashBox={handleTrashBox}
|
handleTrashBox={handleTrashBox}
|
||||||
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
||||||
myIssueProjectId={myIssueProjectId}
|
myIssueProjectId={myIssueProjectId}
|
||||||
|
@ -19,7 +19,8 @@ type Props = {
|
|||||||
disableUserActions: boolean;
|
disableUserActions: boolean;
|
||||||
disableAddIssueOption?: boolean;
|
disableAddIssueOption?: boolean;
|
||||||
dragDisabled: boolean;
|
dragDisabled: boolean;
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit" | "updateDraft") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
|
handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void;
|
||||||
handleTrashBox: (isDragging: boolean) => void;
|
handleTrashBox: (isDragging: boolean) => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||||
@ -37,6 +38,7 @@ export const AllBoards: React.FC<Props> = ({
|
|||||||
disableAddIssueOption = false,
|
disableAddIssueOption = false,
|
||||||
dragDisabled,
|
dragDisabled,
|
||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
|
handleDraftIssueAction,
|
||||||
handleTrashBox,
|
handleTrashBox,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
myIssueProjectId,
|
myIssueProjectId,
|
||||||
@ -94,6 +96,7 @@ export const AllBoards: React.FC<Props> = ({
|
|||||||
dragDisabled={dragDisabled}
|
dragDisabled={dragDisabled}
|
||||||
groupTitle={singleGroup}
|
groupTitle={singleGroup}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
|
handleDraftIssueAction={handleDraftIssueAction}
|
||||||
handleTrashBox={handleTrashBox}
|
handleTrashBox={handleTrashBox}
|
||||||
openIssuesListModal={openIssuesListModal ?? null}
|
openIssuesListModal={openIssuesListModal ?? null}
|
||||||
handleMyIssueOpen={handleMyIssueOpen}
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
|
@ -24,6 +24,7 @@ type Props = {
|
|||||||
dragDisabled: boolean;
|
dragDisabled: boolean;
|
||||||
groupTitle: string;
|
groupTitle: string;
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
|
handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void;
|
||||||
handleTrashBox: (isDragging: boolean) => void;
|
handleTrashBox: (isDragging: boolean) => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
handleMyIssueOpen?: (issue: IIssue) => void;
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
@ -41,6 +42,7 @@ export const SingleBoard: React.FC<Props> = ({
|
|||||||
disableAddIssueOption = false,
|
disableAddIssueOption = false,
|
||||||
dragDisabled,
|
dragDisabled,
|
||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
|
handleDraftIssueAction,
|
||||||
handleTrashBox,
|
handleTrashBox,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
handleMyIssueOpen,
|
handleMyIssueOpen,
|
||||||
@ -136,6 +138,16 @@ export const SingleBoard: React.FC<Props> = ({
|
|||||||
editIssue={() => handleIssueAction(issue, "edit")}
|
editIssue={() => handleIssueAction(issue, "edit")}
|
||||||
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
||||||
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
||||||
|
handleDraftIssueEdit={
|
||||||
|
handleDraftIssueAction
|
||||||
|
? () => handleDraftIssueAction(issue, "edit")
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
handleDraftIssueDelete={() =>
|
||||||
|
handleDraftIssueAction
|
||||||
|
? handleDraftIssueAction(issue, "delete")
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
handleTrashBox={handleTrashBox}
|
handleTrashBox={handleTrashBox}
|
||||||
handleMyIssueOpen={handleMyIssueOpen}
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
removeIssue={() => {
|
removeIssue={() => {
|
||||||
@ -155,7 +167,7 @@ export const SingleBoard: React.FC<Props> = ({
|
|||||||
display: displayFilters?.order_by === "sort_order" ? "inline" : "none",
|
display: displayFilters?.order_by === "sort_order" ? "inline" : "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{provided.placeholder}
|
<>{provided.placeholder}</>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{displayFilters?.group_by !== "created_by" && (
|
{displayFilters?.group_by !== "created_by" && (
|
||||||
|
@ -60,6 +60,8 @@ type Props = {
|
|||||||
handleMyIssueOpen?: (issue: IIssue) => void;
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
removeIssue?: (() => void) | null;
|
removeIssue?: (() => void) | null;
|
||||||
handleDeleteIssue: (issue: IIssue) => void;
|
handleDeleteIssue: (issue: IIssue) => void;
|
||||||
|
handleDraftIssueEdit?: () => void;
|
||||||
|
handleDraftIssueDelete?: () => void;
|
||||||
handleTrashBox: (isDragging: boolean) => void;
|
handleTrashBox: (isDragging: boolean) => void;
|
||||||
disableUserActions: boolean;
|
disableUserActions: boolean;
|
||||||
user: ICurrentUserResponse | undefined;
|
user: ICurrentUserResponse | undefined;
|
||||||
@ -79,6 +81,8 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
removeIssue,
|
removeIssue,
|
||||||
groupTitle,
|
groupTitle,
|
||||||
handleDeleteIssue,
|
handleDeleteIssue,
|
||||||
|
handleDraftIssueEdit,
|
||||||
|
handleDraftIssueDelete,
|
||||||
handleTrashBox,
|
handleTrashBox,
|
||||||
disableUserActions,
|
disableUserActions,
|
||||||
user,
|
user,
|
||||||
@ -99,6 +103,8 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||||
|
|
||||||
|
const isDraftIssue = router.pathname.includes("draft-issues");
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const partialUpdateIssue = useCallback(
|
const partialUpdateIssue = useCallback(
|
||||||
@ -211,29 +217,47 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
>
|
>
|
||||||
{!isNotAllowed && (
|
{!isNotAllowed && (
|
||||||
<>
|
<>
|
||||||
<ContextMenu.Item Icon={PencilIcon} onClick={editIssue}>
|
<ContextMenu.Item
|
||||||
|
Icon={PencilIcon}
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssue && handleDraftIssueEdit) handleDraftIssueEdit();
|
||||||
|
else editIssue();
|
||||||
|
}}
|
||||||
|
>
|
||||||
Edit issue
|
Edit issue
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
<ContextMenu.Item Icon={ClipboardDocumentCheckIcon} onClick={makeIssueCopy}>
|
{!isDraftIssue && (
|
||||||
Make a copy...
|
<ContextMenu.Item Icon={ClipboardDocumentCheckIcon} onClick={makeIssueCopy}>
|
||||||
</ContextMenu.Item>
|
Make a copy...
|
||||||
<ContextMenu.Item Icon={TrashIcon} onClick={() => handleDeleteIssue(issue)}>
|
</ContextMenu.Item>
|
||||||
|
)}
|
||||||
|
<ContextMenu.Item
|
||||||
|
Icon={TrashIcon}
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssue && handleDraftIssueDelete) handleDraftIssueDelete();
|
||||||
|
else handleDeleteIssue(issue);
|
||||||
|
}}
|
||||||
|
>
|
||||||
Delete issue
|
Delete issue
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<ContextMenu.Item Icon={LinkIcon} onClick={handleCopyText}>
|
{!isDraftIssue && (
|
||||||
Copy issue link
|
<ContextMenu.Item Icon={LinkIcon} onClick={handleCopyText}>
|
||||||
</ContextMenu.Item>
|
Copy issue link
|
||||||
<a
|
|
||||||
href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>
|
|
||||||
<ContextMenu.Item Icon={ArrowTopRightOnSquareIcon}>
|
|
||||||
Open issue in new tab
|
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
</a>
|
)}
|
||||||
|
{!isDraftIssue && (
|
||||||
|
<a
|
||||||
|
href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
>
|
||||||
|
<ContextMenu.Item Icon={ArrowTopRightOnSquareIcon}>
|
||||||
|
Open issue in new tab
|
||||||
|
</ContextMenu.Item>
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
<div
|
<div
|
||||||
className={`mb-3 rounded bg-custom-background-100 shadow ${
|
className={`mb-3 rounded bg-custom-background-100 shadow ${
|
||||||
@ -268,13 +292,18 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CustomMenu.MenuItem onClick={editIssue}>
|
<CustomMenu.MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssue && handleDraftIssueEdit) handleDraftIssueEdit();
|
||||||
|
else editIssue();
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="flex items-center justify-start gap-2">
|
<div className="flex items-center justify-start gap-2">
|
||||||
<PencilIcon className="h-4 w-4" />
|
<PencilIcon className="h-4 w-4" />
|
||||||
<span>Edit issue</span>
|
<span>Edit issue</span>
|
||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
{type !== "issue" && removeIssue && (
|
{type !== "issue" && removeIssue && !isDraftIssue && (
|
||||||
<CustomMenu.MenuItem onClick={removeIssue}>
|
<CustomMenu.MenuItem onClick={removeIssue}>
|
||||||
<div className="flex items-center justify-start gap-2">
|
<div className="flex items-center justify-start gap-2">
|
||||||
<XMarkIcon className="h-4 w-4" />
|
<XMarkIcon className="h-4 w-4" />
|
||||||
@ -282,18 +311,25 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
)}
|
)}
|
||||||
<CustomMenu.MenuItem onClick={() => handleDeleteIssue(issue)}>
|
<CustomMenu.MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssue && handleDraftIssueDelete) handleDraftIssueDelete();
|
||||||
|
else handleDeleteIssue(issue);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="flex items-center justify-start gap-2">
|
<div className="flex items-center justify-start gap-2">
|
||||||
<TrashIcon className="h-4 w-4" />
|
<TrashIcon className="h-4 w-4" />
|
||||||
<span>Delete issue</span>
|
<span>Delete issue</span>
|
||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
<CustomMenu.MenuItem onClick={handleCopyText}>
|
{!isDraftIssue && (
|
||||||
<div className="flex items-center justify-start gap-2">
|
<CustomMenu.MenuItem onClick={handleCopyText}>
|
||||||
<LinkIcon className="h-4 w-4" />
|
<div className="flex items-center justify-start gap-2">
|
||||||
<span>Copy issue Link</span>
|
<LinkIcon className="h-4 w-4" />
|
||||||
</div>
|
<span>Copy issue Link</span>
|
||||||
</CustomMenu.MenuItem>
|
</div>
|
||||||
|
</CustomMenu.MenuItem>
|
||||||
|
)}
|
||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -308,7 +344,10 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-sm text-left break-words line-clamp-2"
|
className="text-sm text-left break-words line-clamp-2"
|
||||||
onClick={openPeekOverview}
|
onClick={() => {
|
||||||
|
if (isDraftIssue && handleDraftIssueEdit) handleDraftIssueEdit();
|
||||||
|
else openPeekOverview();
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{issue.name}
|
{issue.name}
|
||||||
</button>
|
</button>
|
||||||
|
@ -22,6 +22,7 @@ import { FiltersList, AllViews } from "components/core";
|
|||||||
import {
|
import {
|
||||||
CreateUpdateIssueModal,
|
CreateUpdateIssueModal,
|
||||||
DeleteIssueModal,
|
DeleteIssueModal,
|
||||||
|
DeleteDraftIssueModal,
|
||||||
IssuePeekOverview,
|
IssuePeekOverview,
|
||||||
CreateUpdateDraftIssueModal,
|
CreateUpdateDraftIssueModal,
|
||||||
} from "components/issues";
|
} from "components/issues";
|
||||||
@ -77,9 +78,11 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
|
|
||||||
// selected draft issue
|
// selected draft issue
|
||||||
const [selectedDraftIssue, setSelectedDraftIssue] = useState<IIssue | null>(null);
|
const [selectedDraftIssue, setSelectedDraftIssue] = useState<IIssue | null>(null);
|
||||||
|
const [selectedDraftForDelete, setSelectDraftForDelete] = useState<IIssue | null>(null);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
|
const isDraftIssues = router.asPath.includes("draft-issues");
|
||||||
|
|
||||||
const { user } = useUserAuth();
|
const { user } = useUserAuth();
|
||||||
|
|
||||||
@ -114,7 +117,8 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
[setDeleteIssueModal, setIssueToDelete]
|
[setDeleteIssueModal, setIssueToDelete]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDraftIssueClick = (issue: any) => setSelectedDraftIssue(issue);
|
const handleDraftIssueClick = useCallback((issue: any) => setSelectedDraftIssue(issue), []);
|
||||||
|
const handleDraftIssueDelete = useCallback((issue: any) => setSelectDraftForDelete(issue), []);
|
||||||
|
|
||||||
const handleOnDragEnd = useCallback(
|
const handleOnDragEnd = useCallback(
|
||||||
async (result: DropResult) => {
|
async (result: DropResult) => {
|
||||||
@ -345,15 +349,22 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleIssueAction = useCallback(
|
const handleIssueAction = useCallback(
|
||||||
(issue: IIssue, action: "copy" | "edit" | "delete" | "updateDraft") => {
|
(issue: IIssue, action: "copy" | "edit" | "delete") => {
|
||||||
if (action === "copy") makeIssueCopy(issue);
|
if (action === "copy") makeIssueCopy(issue);
|
||||||
else if (action === "edit") handleEditIssue(issue);
|
else if (action === "edit") handleEditIssue(issue);
|
||||||
else if (action === "delete") handleDeleteIssue(issue);
|
else if (action === "delete") handleDeleteIssue(issue);
|
||||||
else if (action === "updateDraft") handleDraftIssueClick(issue);
|
|
||||||
},
|
},
|
||||||
[makeIssueCopy, handleEditIssue, handleDeleteIssue]
|
[makeIssueCopy, handleEditIssue, handleDeleteIssue]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleDraftIssueAction = useCallback(
|
||||||
|
(issue: IIssue, action: "edit" | "delete") => {
|
||||||
|
if (action === "edit") handleDraftIssueClick(issue);
|
||||||
|
else if (action === "delete") handleDraftIssueDelete(issue);
|
||||||
|
},
|
||||||
|
[handleDraftIssueClick, handleDraftIssueDelete]
|
||||||
|
);
|
||||||
|
|
||||||
const removeIssueFromCycle = useCallback(
|
const removeIssueFromCycle = useCallback(
|
||||||
(bridgeId: string, issueId: string) => {
|
(bridgeId: string, issueId: string) => {
|
||||||
if (!workspaceSlug || !projectId || !cycleId) return;
|
if (!workspaceSlug || !projectId || !cycleId) return;
|
||||||
@ -494,6 +505,11 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
data={issueToDelete}
|
data={issueToDelete}
|
||||||
user={user}
|
user={user}
|
||||||
/>
|
/>
|
||||||
|
<DeleteDraftIssueModal
|
||||||
|
data={selectedDraftForDelete}
|
||||||
|
isOpen={selectedDraftForDelete !== null}
|
||||||
|
handleClose={() => setSelectDraftForDelete(null)}
|
||||||
|
/>
|
||||||
|
|
||||||
{areFiltersApplied && (
|
{areFiltersApplied && (
|
||||||
<>
|
<>
|
||||||
@ -550,23 +566,28 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
displayFilters.group_by === "assignees"
|
displayFilters.group_by === "assignees"
|
||||||
}
|
}
|
||||||
emptyState={{
|
emptyState={{
|
||||||
title: cycleId
|
title: isDraftIssues
|
||||||
|
? "Draft issues will appear here"
|
||||||
|
: cycleId
|
||||||
? "Cycle issues will appear here"
|
? "Cycle issues will appear here"
|
||||||
: moduleId
|
: moduleId
|
||||||
? "Module issues will appear here"
|
? "Module issues will appear here"
|
||||||
: "Project issues will appear here",
|
: "Project issues will appear here",
|
||||||
description:
|
description: isDraftIssues
|
||||||
"Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done.",
|
? "Draft issues are issues that are not yet created."
|
||||||
primaryButton: {
|
: "Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done.",
|
||||||
icon: <PlusIcon className="h-4 w-4" />,
|
primaryButton: !isDraftIssues
|
||||||
text: "New Issue",
|
? {
|
||||||
onClick: () => {
|
icon: <PlusIcon className="h-4 w-4" />,
|
||||||
const e = new KeyboardEvent("keydown", {
|
text: "New Issue",
|
||||||
key: "c",
|
onClick: () => {
|
||||||
});
|
const e = new KeyboardEvent("keydown", {
|
||||||
document.dispatchEvent(e);
|
key: "c",
|
||||||
},
|
});
|
||||||
},
|
document.dispatchEvent(e);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
secondaryButton:
|
secondaryButton:
|
||||||
cycleId || moduleId ? (
|
cycleId || moduleId ? (
|
||||||
<SecondaryButton
|
<SecondaryButton
|
||||||
@ -580,6 +601,7 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
}}
|
}}
|
||||||
handleOnDragEnd={handleOnDragEnd}
|
handleOnDragEnd={handleOnDragEnd}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
|
handleDraftIssueAction={handleDraftIssueAction}
|
||||||
openIssuesListModal={openIssuesListModal ?? null}
|
openIssuesListModal={openIssuesListModal ?? null}
|
||||||
removeIssue={cycleId ? removeIssueFromCycle : moduleId ? removeIssueFromModule : null}
|
removeIssue={cycleId ? removeIssueFromCycle : moduleId ? removeIssueFromModule : null}
|
||||||
trashBox={trashBox}
|
trashBox={trashBox}
|
||||||
|
@ -14,7 +14,8 @@ import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from
|
|||||||
type Props = {
|
type Props = {
|
||||||
states: IState[] | undefined;
|
states: IState[] | undefined;
|
||||||
addIssueToGroup: (groupTitle: string) => void;
|
addIssueToGroup: (groupTitle: string) => void;
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit" | "updateDraft") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
|
handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
myIssueProjectId?: string | null;
|
myIssueProjectId?: string | null;
|
||||||
handleMyIssueOpen?: (issue: IIssue) => void;
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
@ -36,6 +37,7 @@ export const AllLists: React.FC<Props> = ({
|
|||||||
myIssueProjectId,
|
myIssueProjectId,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
states,
|
states,
|
||||||
|
handleDraftIssueAction,
|
||||||
user,
|
user,
|
||||||
userAuth,
|
userAuth,
|
||||||
viewProps,
|
viewProps,
|
||||||
@ -82,6 +84,7 @@ export const AllLists: React.FC<Props> = ({
|
|||||||
groupTitle={singleGroup}
|
groupTitle={singleGroup}
|
||||||
currentState={currentState}
|
currentState={currentState}
|
||||||
addIssueToGroup={() => addIssueToGroup(singleGroup)}
|
addIssueToGroup={() => addIssueToGroup(singleGroup)}
|
||||||
|
handleDraftIssueAction={handleDraftIssueAction}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
handleMyIssueOpen={handleMyIssueOpen}
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
openIssuesListModal={openIssuesListModal}
|
openIssuesListModal={openIssuesListModal}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useCallback, useState } from "react";
|
import React, { useCallback, useState } from "react";
|
||||||
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
@ -18,6 +17,7 @@ import {
|
|||||||
ViewPrioritySelect,
|
ViewPrioritySelect,
|
||||||
ViewStartDateSelect,
|
ViewStartDateSelect,
|
||||||
ViewStateSelect,
|
ViewStateSelect,
|
||||||
|
CreateUpdateDraftIssueModal,
|
||||||
} from "components/issues";
|
} from "components/issues";
|
||||||
// ui
|
// ui
|
||||||
import { Tooltip, CustomMenu, ContextMenu } from "components/ui";
|
import { Tooltip, CustomMenu, ContextMenu } from "components/ui";
|
||||||
@ -62,6 +62,7 @@ type Props = {
|
|||||||
removeIssue?: (() => void) | null;
|
removeIssue?: (() => void) | null;
|
||||||
handleDeleteIssue: (issue: IIssue) => void;
|
handleDeleteIssue: (issue: IIssue) => void;
|
||||||
handleDraftIssueSelect?: (issue: IIssue) => void;
|
handleDraftIssueSelect?: (issue: IIssue) => void;
|
||||||
|
handleDraftIssueDelete?: (issue: IIssue) => void;
|
||||||
handleMyIssueOpen?: (issue: IIssue) => void;
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
disableUserActions: boolean;
|
disableUserActions: boolean;
|
||||||
user: ICurrentUserResponse | undefined;
|
user: ICurrentUserResponse | undefined;
|
||||||
@ -77,6 +78,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
makeIssueCopy,
|
makeIssueCopy,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
groupTitle,
|
groupTitle,
|
||||||
|
handleDraftIssueDelete,
|
||||||
handleDeleteIssue,
|
handleDeleteIssue,
|
||||||
handleMyIssueOpen,
|
handleMyIssueOpen,
|
||||||
disableUserActions,
|
disableUserActions,
|
||||||
@ -208,26 +210,45 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
>
|
>
|
||||||
{!isNotAllowed && (
|
{!isNotAllowed && (
|
||||||
<>
|
<>
|
||||||
<ContextMenu.Item Icon={PencilIcon} onClick={editIssue}>
|
<ContextMenu.Item
|
||||||
|
Icon={PencilIcon}
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssues && handleDraftIssueSelect) handleDraftIssueSelect(issue);
|
||||||
|
else editIssue();
|
||||||
|
}}
|
||||||
|
>
|
||||||
Edit issue
|
Edit issue
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
<ContextMenu.Item Icon={ClipboardDocumentCheckIcon} onClick={makeIssueCopy}>
|
{!isDraftIssues && (
|
||||||
Make a copy...
|
<ContextMenu.Item Icon={ClipboardDocumentCheckIcon} onClick={makeIssueCopy}>
|
||||||
</ContextMenu.Item>
|
Make a copy...
|
||||||
<ContextMenu.Item Icon={TrashIcon} onClick={() => handleDeleteIssue(issue)}>
|
</ContextMenu.Item>
|
||||||
|
)}
|
||||||
|
<ContextMenu.Item
|
||||||
|
Icon={TrashIcon}
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssues && handleDraftIssueDelete) handleDraftIssueDelete(issue);
|
||||||
|
else handleDeleteIssue(issue);
|
||||||
|
}}
|
||||||
|
>
|
||||||
Delete issue
|
Delete issue
|
||||||
</ContextMenu.Item>
|
</ContextMenu.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<ContextMenu.Item Icon={LinkIcon} onClick={handleCopyText}>
|
{!isDraftIssues && (
|
||||||
Copy issue link
|
<>
|
||||||
</ContextMenu.Item>
|
<ContextMenu.Item Icon={LinkIcon} onClick={handleCopyText}>
|
||||||
<a href={issuePath} target="_blank" rel="noreferrer noopener">
|
Copy issue link
|
||||||
<ContextMenu.Item Icon={ArrowTopRightOnSquareIcon}>
|
</ContextMenu.Item>
|
||||||
Open issue in new tab
|
<a href={issuePath} target="_blank" rel="noreferrer noopener">
|
||||||
</ContextMenu.Item>
|
<ContextMenu.Item Icon={ArrowTopRightOnSquareIcon}>
|
||||||
</a>
|
Open issue in new tab
|
||||||
|
</ContextMenu.Item>
|
||||||
|
</a>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="flex items-center justify-between px-4 py-2.5 gap-10 border-b border-custom-border-200 bg-custom-background-100 last:border-b-0"
|
className="flex items-center justify-between px-4 py-2.5 gap-10 border-b border-custom-border-200 bg-custom-background-100 last:border-b-0"
|
||||||
onContextMenu={(e) => {
|
onContextMenu={(e) => {
|
||||||
@ -254,8 +275,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
className="truncate text-[0.825rem] text-custom-text-100"
|
className="truncate text-[0.825rem] text-custom-text-100"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!isDraftIssues) openPeekOverview(issue);
|
if (!isDraftIssues) openPeekOverview(issue);
|
||||||
|
if (isDraftIssues && handleDraftIssueSelect) handleDraftIssueSelect(issue);
|
||||||
if (handleDraftIssueSelect) handleDraftIssueSelect(issue);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{issue.name}
|
{issue.name}
|
||||||
@ -354,7 +374,12 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
{type && !isNotAllowed && (
|
{type && !isNotAllowed && (
|
||||||
<CustomMenu width="auto" ellipsis>
|
<CustomMenu width="auto" ellipsis>
|
||||||
<CustomMenu.MenuItem onClick={editIssue}>
|
<CustomMenu.MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssues && handleDraftIssueSelect) handleDraftIssueSelect(issue);
|
||||||
|
else editIssue();
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="flex items-center justify-start gap-2">
|
<div className="flex items-center justify-start gap-2">
|
||||||
<PencilIcon className="h-4 w-4" />
|
<PencilIcon className="h-4 w-4" />
|
||||||
<span>Edit issue</span>
|
<span>Edit issue</span>
|
||||||
@ -368,18 +393,25 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
)}
|
)}
|
||||||
<CustomMenu.MenuItem onClick={() => handleDeleteIssue(issue)}>
|
<CustomMenu.MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
if (isDraftIssues && handleDraftIssueDelete) handleDraftIssueDelete(issue);
|
||||||
|
else handleDeleteIssue(issue);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="flex items-center justify-start gap-2">
|
<div className="flex items-center justify-start gap-2">
|
||||||
<TrashIcon className="h-4 w-4" />
|
<TrashIcon className="h-4 w-4" />
|
||||||
<span>Delete issue</span>
|
<span>Delete issue</span>
|
||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
<CustomMenu.MenuItem onClick={handleCopyText}>
|
{!isDraftIssues && (
|
||||||
<div className="flex items-center justify-start gap-2">
|
<CustomMenu.MenuItem onClick={handleCopyText}>
|
||||||
<LinkIcon className="h-4 w-4" />
|
<div className="flex items-center justify-start gap-2">
|
||||||
<span>Copy issue link</span>
|
<LinkIcon className="h-4 w-4" />
|
||||||
</div>
|
<span>Copy issue link</span>
|
||||||
</CustomMenu.MenuItem>
|
</div>
|
||||||
|
</CustomMenu.MenuItem>
|
||||||
|
)}
|
||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -39,7 +39,8 @@ type Props = {
|
|||||||
currentState?: IState | null;
|
currentState?: IState | null;
|
||||||
groupTitle: string;
|
groupTitle: string;
|
||||||
addIssueToGroup: () => void;
|
addIssueToGroup: () => void;
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit" | "updateDraft") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
|
handleDraftIssueAction?: (issue: IIssue, action: "edit" | "delete") => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
handleMyIssueOpen?: (issue: IIssue) => void;
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||||
@ -56,6 +57,7 @@ export const SingleList: React.FC<Props> = ({
|
|||||||
addIssueToGroup,
|
addIssueToGroup,
|
||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
|
handleDraftIssueAction,
|
||||||
handleMyIssueOpen,
|
handleMyIssueOpen,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
disableUserActions,
|
disableUserActions,
|
||||||
@ -253,7 +255,16 @@ export const SingleList: React.FC<Props> = ({
|
|||||||
editIssue={() => handleIssueAction(issue, "edit")}
|
editIssue={() => handleIssueAction(issue, "edit")}
|
||||||
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
||||||
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
||||||
handleDraftIssueSelect={() => handleIssueAction(issue, "updateDraft")}
|
handleDraftIssueSelect={
|
||||||
|
handleDraftIssueAction
|
||||||
|
? () => handleDraftIssueAction(issue, "edit")
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
handleDraftIssueDelete={
|
||||||
|
handleDraftIssueAction
|
||||||
|
? () => handleDraftIssueAction(issue, "delete")
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
handleMyIssueOpen={handleMyIssueOpen}
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
removeIssue={() => {
|
removeIssue={() => {
|
||||||
if (removeIssue !== null && issue.bridge_id)
|
if (removeIssue !== null && issue.bridge_id)
|
||||||
|
145
web/components/issues/delete-draft-issue-modal.tsx
Normal file
145
web/components/issues/delete-draft-issue-modal.tsx
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
import { mutate } from "swr";
|
||||||
|
|
||||||
|
// headless ui
|
||||||
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
|
// services
|
||||||
|
import issueServices from "services/issues.service";
|
||||||
|
// hooks
|
||||||
|
import useIssuesView from "hooks/use-issues-view";
|
||||||
|
import useToast from "hooks/use-toast";
|
||||||
|
// icons
|
||||||
|
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||||
|
// ui
|
||||||
|
import { SecondaryButton, DangerButton } from "components/ui";
|
||||||
|
// types
|
||||||
|
import type { IIssue, ICurrentUserResponse } from "types";
|
||||||
|
// fetch-keys
|
||||||
|
import { PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS } from "constants/fetch-keys";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen: boolean;
|
||||||
|
handleClose: () => void;
|
||||||
|
data: IIssue | null;
|
||||||
|
user?: ICurrentUserResponse;
|
||||||
|
onSubmit?: () => Promise<void> | void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DeleteDraftIssueModal: React.FC<Props> = (props) => {
|
||||||
|
const { isOpen, handleClose, data, user, onSubmit } = props;
|
||||||
|
|
||||||
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const { workspaceSlug, projectId } = router.query;
|
||||||
|
|
||||||
|
const { params } = useIssuesView();
|
||||||
|
|
||||||
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsDeleteLoading(false);
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
setIsDeleteLoading(false);
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeletion = async () => {
|
||||||
|
if (!workspaceSlug || !data) return;
|
||||||
|
|
||||||
|
setIsDeleteLoading(true);
|
||||||
|
|
||||||
|
await issueServices
|
||||||
|
.deleteDraftIssue(workspaceSlug as string, data.project, data.id)
|
||||||
|
.then(() => {
|
||||||
|
setIsDeleteLoading(false);
|
||||||
|
handleClose();
|
||||||
|
mutate(PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS(projectId as string, params));
|
||||||
|
setToastAlert({
|
||||||
|
title: "Success",
|
||||||
|
message: "Draft Issue deleted successfully",
|
||||||
|
type: "success",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
handleClose();
|
||||||
|
setToastAlert({
|
||||||
|
title: "Error",
|
||||||
|
message: "Something went wrong",
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
|
setIsDeleteLoading(false);
|
||||||
|
});
|
||||||
|
if (onSubmit) await onSubmit();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition.Root show={isOpen} as={React.Fragment}>
|
||||||
|
<Dialog as="div" className="relative z-20" onClose={onClose}>
|
||||||
|
<Transition.Child
|
||||||
|
as={React.Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="fixed inset-0 bg-custom-backdrop bg-opacity-50 transition-opacity" />
|
||||||
|
</Transition.Child>
|
||||||
|
|
||||||
|
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||||
|
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||||
|
<Transition.Child
|
||||||
|
as={React.Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
>
|
||||||
|
<Dialog.Panel className="relative transform overflow-hidden rounded-lg border border-custom-border-200 bg-custom-background-100 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-2xl">
|
||||||
|
<div className="flex flex-col gap-6 p-6">
|
||||||
|
<div className="flex w-full items-center justify-start gap-6">
|
||||||
|
<span className="place-items-center rounded-full bg-red-500/20 p-4">
|
||||||
|
<ExclamationTriangleIcon
|
||||||
|
className="h-6 w-6 text-red-600"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span className="flex items-center justify-start">
|
||||||
|
<h3 className="text-xl font-medium 2xl:text-2xl">Delete Draft Issue</h3>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
<p className="text-sm text-custom-text-200">
|
||||||
|
Are you sure you want to delete issue{" "}
|
||||||
|
<span className="break-words font-medium text-custom-text-100">
|
||||||
|
{data?.project_detail.identifier}-{data?.sequence_id}
|
||||||
|
</span>
|
||||||
|
{""}? All of the data related to the draft issue will be permanently removed.
|
||||||
|
This action cannot be undone.
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<SecondaryButton onClick={onClose}>Cancel</SecondaryButton>
|
||||||
|
<DangerButton onClick={handleDeletion} loading={isDeleteLoading}>
|
||||||
|
{isDeleteLoading ? "Deleting..." : "Delete Issue"}
|
||||||
|
</DangerButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog.Panel>
|
||||||
|
</Transition.Child>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</Transition.Root>
|
||||||
|
);
|
||||||
|
};
|
@ -133,9 +133,15 @@ export const IssueForm: FC<IssueFormProps> = (props) => {
|
|||||||
|
|
||||||
const issueName = watch("name");
|
const issueName = watch("name");
|
||||||
|
|
||||||
const payload = {
|
const payload: Partial<IIssue> = {
|
||||||
name: getValues("name"),
|
name: getValues("name"),
|
||||||
description: getValues("description"),
|
description: getValues("description"),
|
||||||
|
state: getValues("state"),
|
||||||
|
priority: getValues("priority"),
|
||||||
|
assignees: getValues("assignees"),
|
||||||
|
target_date: getValues("target_date"),
|
||||||
|
labels: getValues("labels"),
|
||||||
|
project: getValues("project"),
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -17,5 +17,8 @@ export * from "./label";
|
|||||||
export * from "./issue-reaction";
|
export * from "./issue-reaction";
|
||||||
export * from "./peek-overview";
|
export * from "./peek-overview";
|
||||||
export * from "./confirm-issue-discard";
|
export * from "./confirm-issue-discard";
|
||||||
|
|
||||||
|
// draft issue
|
||||||
export * from "./draft-issue-form";
|
export * from "./draft-issue-form";
|
||||||
export * from "./draft-issue-modal";
|
export * from "./draft-issue-modal";
|
||||||
|
export * from "./delete-draft-issue-modal";
|
||||||
|
@ -38,6 +38,9 @@ export const WorkspaceSidebarQuickAction = () => {
|
|||||||
"priority",
|
"priority",
|
||||||
"dueDate",
|
"dueDate",
|
||||||
"priority",
|
"priority",
|
||||||
|
"state",
|
||||||
|
"startDate",
|
||||||
|
"project",
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -47,7 +50,7 @@ export const WorkspaceSidebarQuickAction = () => {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center justify-between w-full rounded cursor-pointer px-4 gap-1 ${
|
className={`flex items-center justify-between w-full rounded cursor-pointer px-2 gap-1 ${
|
||||||
store?.theme?.sidebarCollapsed
|
store?.theme?.sidebarCollapsed
|
||||||
? "px-2 hover:bg-custom-sidebar-background-80"
|
? "px-2 hover:bg-custom-sidebar-background-80"
|
||||||
: "px-3 shadow border-[0.5px] border-custom-border-300"
|
: "px-3 shadow border-[0.5px] border-custom-border-300"
|
||||||
@ -80,7 +83,7 @@ export const WorkspaceSidebarQuickAction = () => {
|
|||||||
<div>
|
<div>
|
||||||
<Menu.Button
|
<Menu.Button
|
||||||
type="button"
|
type="button"
|
||||||
className={`flex items-center justify-center rounded flex-shrink-0 p-2 ${
|
className={`flex items-center justify-center rounded flex-shrink-0 p-1.5 ${
|
||||||
open ? "rotate-180 pl-0" : "rotate-0 pr-0"
|
open ? "rotate-180 pl-0" : "rotate-0 pr-0"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@ -108,7 +111,7 @@ export const WorkspaceSidebarQuickAction = () => {
|
|||||||
>
|
>
|
||||||
<PenSquare
|
<PenSquare
|
||||||
size={16}
|
size={16}
|
||||||
className="!text-lg !leading-4 text-custom-sidebar-text-300 mx-2"
|
className="!text-lg !leading-4 text-custom-sidebar-text-300 mr-2"
|
||||||
/>
|
/>
|
||||||
Last Drafted Issue
|
Last Drafted Issue
|
||||||
</button>
|
</button>
|
||||||
|
@ -55,7 +55,7 @@ const ProjectDraftIssues: NextPage = () => {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/issues/`)}
|
onClick={() => router.push(`/${workspaceSlug}/projects/${projectId}/issues/`)}
|
||||||
className="flex items-center gap-1.5 rounded-full border border-custom-border-200 px-3 py-1.5 text-xs"
|
className="flex items-center gap-1.5 rounded border border-custom-border-200 px-3 py-1.5 text-xs"
|
||||||
>
|
>
|
||||||
<PenSquare className="h-3 w-3 text-custom-text-300" />
|
<PenSquare className="h-3 w-3 text-custom-text-300" />
|
||||||
<span>Draft Issues</span>
|
<span>Draft Issues</span>
|
||||||
|
Loading…
Reference in New Issue
Block a user