mirror of
https://github.com/makeplane/plane.git
synced 2026-02-05 13:39:37 -06:00
[WEB-3827] refactor: work item widget components (#6902)
This commit is contained in:
committed by
GitHub
parent
9eeff158d5
commit
a3fd616ec4
@@ -1,8 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { Layers, Link, Paperclip, Waypoints } from "lucide-react";
|
||||
//i18n
|
||||
// plane imports
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
// components
|
||||
import {
|
||||
IssueAttachmentActionButton,
|
||||
@@ -10,6 +12,7 @@ import {
|
||||
RelationActionButton,
|
||||
SubIssuesActionButton,
|
||||
IssueDetailWidgetButton,
|
||||
TWorkItemWidgets,
|
||||
} from "@/components/issues/issue-detail-widgets";
|
||||
|
||||
type Props = {
|
||||
@@ -17,58 +20,74 @@ type Props = {
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
disabled: boolean;
|
||||
issueServiceType: TIssueServiceType;
|
||||
hideWidgets?: TWorkItemWidgets[];
|
||||
};
|
||||
|
||||
export const IssueDetailWidgetActionButtons: FC<Props> = (props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled } = props;
|
||||
const { workspaceSlug, projectId, issueId, disabled, issueServiceType, hideWidgets } = props;
|
||||
// translation
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="flex items-center flex-wrap gap-2">
|
||||
<SubIssuesActionButton
|
||||
issueId={issueId}
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("issue.add.sub_issue")}
|
||||
icon={<Layers className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<RelationActionButton
|
||||
issueId={issueId}
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("issue.add.relation")}
|
||||
icon={<Waypoints className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<IssueLinksActionButton
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("issue.add.link")}
|
||||
icon={<Link className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<IssueAttachmentActionButton
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("common.attach")}
|
||||
icon={<Paperclip className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
/>
|
||||
{!hideWidgets?.includes("sub-work-items") && (
|
||||
<SubIssuesActionButton
|
||||
issueId={issueId}
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("issue.add.sub_issue")}
|
||||
icon={<Layers className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
{!hideWidgets?.includes("relations") && (
|
||||
<RelationActionButton
|
||||
issueId={issueId}
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("issue.add.relation")}
|
||||
icon={<Waypoints className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
{!hideWidgets?.includes("links") && (
|
||||
<IssueLinksActionButton
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("issue.add.link")}
|
||||
icon={<Link className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
{!hideWidgets?.includes("attachments") && (
|
||||
<IssueAttachmentActionButton
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
customButton={
|
||||
<IssueDetailWidgetButton
|
||||
title={t("common.attach")}
|
||||
icon={<Paperclip className="h-3.5 w-3.5 flex-shrink-0" strokeWidth={2} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,15 +4,14 @@ import React, { FC, useCallback, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { FileRejection, useDropzone } from "react-dropzone";
|
||||
import { Plus } from "lucide-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
// plane ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// hooks
|
||||
import { useIssueDetail } from "@/hooks/store";
|
||||
// plane web hooks
|
||||
import { useFileSize } from "@/plane-web/hooks/use-file-size";
|
||||
|
||||
// local imports
|
||||
import { useAttachmentOperations } from "./helper";
|
||||
|
||||
type Props = {
|
||||
@@ -21,18 +20,11 @@ type Props = {
|
||||
issueId: string;
|
||||
customButton?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const IssueAttachmentActionButton: FC<Props> = observer((props) => {
|
||||
const {
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
customButton,
|
||||
disabled = false,
|
||||
issueServiceType = EIssueServiceType.ISSUES,
|
||||
} = props;
|
||||
const { workspaceSlug, projectId, issueId, customButton, disabled = false, issueServiceType } = props;
|
||||
// state
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
// store hooks
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
import { Collapsible } from "@plane/ui";
|
||||
// components
|
||||
@@ -17,11 +17,11 @@ type Props = {
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const AttachmentsCollapsible: FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType } = props;
|
||||
// store hooks
|
||||
const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType);
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
"use client";
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
// components
|
||||
import {
|
||||
AttachmentsCollapsible,
|
||||
LinksCollapsible,
|
||||
RelationsCollapsible,
|
||||
SubIssuesCollapsible,
|
||||
TWorkItemWidgets,
|
||||
} from "@/components/issues/issue-detail-widgets";
|
||||
// hooks
|
||||
import { useIssueDetail } from "@/hooks/store";
|
||||
@@ -19,31 +22,33 @@ type Props = {
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
disabled: boolean;
|
||||
issueServiceType: TIssueServiceType;
|
||||
hideWidgets?: TWorkItemWidgets[];
|
||||
};
|
||||
|
||||
export const IssueDetailWidgetCollapsibles: FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled } = props;
|
||||
const { workspaceSlug, projectId, issueId, disabled, issueServiceType, hideWidgets } = props;
|
||||
// store hooks
|
||||
const {
|
||||
issue: { getIssueById },
|
||||
subIssues: { subIssuesByIssueId },
|
||||
attachment: { getAttachmentsCountByIssueId, getAttachmentsUploadStatusByIssueId },
|
||||
relation: { getRelationCountByIssueId },
|
||||
} = useIssueDetail();
|
||||
|
||||
} = useIssueDetail(issueServiceType);
|
||||
// derived values
|
||||
const issue = getIssueById(issueId);
|
||||
const subIssues = subIssuesByIssueId(issueId);
|
||||
const ISSUE_RELATION_OPTIONS = useTimeLineRelationOptions();
|
||||
const issueRelationsCount = getRelationCountByIssueId(issueId, ISSUE_RELATION_OPTIONS);
|
||||
|
||||
// render conditions
|
||||
const shouldRenderSubIssues = !!subIssues && subIssues.length > 0;
|
||||
const shouldRenderRelations = issueRelationsCount > 0;
|
||||
const shouldRenderLinks = !!issue?.link_count && issue?.link_count > 0;
|
||||
const shouldRenderSubIssues = !!subIssues && subIssues.length > 0 && !hideWidgets?.includes("sub-work-items");
|
||||
const shouldRenderRelations = issueRelationsCount > 0 && !hideWidgets?.includes("relations");
|
||||
const shouldRenderLinks = !!issue?.link_count && issue?.link_count > 0 && !hideWidgets?.includes("links");
|
||||
const attachmentUploads = getAttachmentsUploadStatusByIssueId(issueId);
|
||||
const attachmentsCount = getAttachmentsCountByIssueId(issueId);
|
||||
const shouldRenderAttachments = attachmentsCount > 0 || (!!attachmentUploads && attachmentUploads.length > 0);
|
||||
const shouldRenderAttachments =
|
||||
attachmentsCount > 0 ||
|
||||
(!!attachmentUploads && attachmentUploads.length > 0 && !hideWidgets?.includes("attachments"));
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
@@ -53,13 +58,25 @@ export const IssueDetailWidgetCollapsibles: FC<Props> = observer((props) => {
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
{shouldRenderRelations && (
|
||||
<RelationsCollapsible workspaceSlug={workspaceSlug} issueId={issueId} disabled={disabled} />
|
||||
<RelationsCollapsible
|
||||
workspaceSlug={workspaceSlug}
|
||||
issueId={issueId}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
{shouldRenderLinks && (
|
||||
<LinksCollapsible workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} disabled={disabled} />
|
||||
<LinksCollapsible
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
{shouldRenderAttachments && (
|
||||
<AttachmentsCollapsible
|
||||
@@ -67,9 +84,9 @@ export const IssueDetailWidgetCollapsibles: FC<Props> = observer((props) => {
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
|
||||
<WorkItemAdditionalWidgets
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { ISearchIssueResponse, TIssue } from "@plane/types";
|
||||
import { ISearchIssueResponse, TIssue, TIssueServiceType } from "@plane/types";
|
||||
import { setToast, TOAST_TYPE } from "@plane/ui";
|
||||
// components
|
||||
import { ExistingIssuesListModal } from "@/components/core";
|
||||
@@ -17,10 +17,11 @@ type Props = {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const IssueDetailWidgetModals: FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId, issueId } = props;
|
||||
const { workspaceSlug, projectId, issueId, issueServiceType } = props;
|
||||
// store hooks
|
||||
const {
|
||||
isIssueLinkModalOpen,
|
||||
@@ -146,6 +147,7 @@ export const IssueDetailWidgetModals: FC<Props> = observer((props) => {
|
||||
isModalOpen={isIssueLinkModalOpen}
|
||||
handleOnClose={handleIssueLinkModalOnClose}
|
||||
linkOperations={handleLinkOperations}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
|
||||
{shouldRenderCreateUpdateModal && (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
import React, { FC } from "react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
// components
|
||||
import { LinkList } from "../../issue-detail/links";
|
||||
@@ -12,11 +11,11 @@ type Props = {
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
disabled: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const IssueLinksCollapsibleContent: FC<Props> = (props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { workspaceSlug, projectId, issueId, disabled, issueServiceType } = props;
|
||||
|
||||
// helper
|
||||
const handleLinkOperations = useLinkOperations(workspaceSlug, projectId, issueId, issueServiceType);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
// hooks
|
||||
import { useIssueDetail } from "@/hooks/store";
|
||||
@@ -10,11 +10,11 @@ import { useIssueDetail } from "@/hooks/store";
|
||||
type Props = {
|
||||
customButton?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const IssueLinksActionButton: FC<Props> = observer((props) => {
|
||||
const { customButton, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { customButton, disabled = false, issueServiceType } = props;
|
||||
// store hooks
|
||||
const { toggleIssueLinkModal } = useIssueDetail(issueServiceType);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
import { Collapsible } from "@plane/ui";
|
||||
// components
|
||||
@@ -14,14 +14,13 @@ type Props = {
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const LinksCollapsible: FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType } = props;
|
||||
// store hooks
|
||||
const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType);
|
||||
|
||||
// derived values
|
||||
const isCollapsibleOpen = openWidgets.includes("links");
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import React, { FC, useMemo } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
import { CollapsibleButton } from "@plane/ui";
|
||||
@@ -14,11 +14,12 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
issueId: string;
|
||||
disabled: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const IssueLinksCollapsibleTitle: FC<Props> = observer((props) => {
|
||||
const { isOpen, issueId, disabled, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { isOpen, issueId, disabled, issueServiceType } = props;
|
||||
// translation
|
||||
const { t } = useTranslation();
|
||||
// store hooks
|
||||
const {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
@@ -16,11 +16,11 @@ type Props = {
|
||||
issueId: string;
|
||||
customButton?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const RelationActionButton: FC<Props> = observer((props) => {
|
||||
const { customButton, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { customButton, issueId, disabled = false, issueServiceType } = props;
|
||||
const { t } = useTranslation();
|
||||
// store hooks
|
||||
const { toggleRelationModal, setRelationKey } = useIssueDetail(issueServiceType);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
import { Collapsible } from "@plane/ui";
|
||||
// components
|
||||
@@ -13,14 +13,13 @@ type Props = {
|
||||
workspaceSlug: string;
|
||||
issueId: string;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const RelationsCollapsible: FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { workspaceSlug, issueId, disabled = false, issueServiceType } = props;
|
||||
// store hooks
|
||||
const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType);
|
||||
|
||||
// derived values
|
||||
const isCollapsibleOpen = openWidgets.includes("relations");
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import React, { FC } from "react";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
// components
|
||||
import {
|
||||
IssueDetailWidgetActionButtons,
|
||||
@@ -7,16 +10,29 @@ import {
|
||||
IssueDetailWidgetModals,
|
||||
} from "@/components/issues/issue-detail-widgets";
|
||||
|
||||
export type TWorkItemWidgets = "sub-work-items" | "relations" | "links" | "attachments";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
disabled: boolean;
|
||||
renderWidgetModals?: boolean;
|
||||
issueServiceType: TIssueServiceType;
|
||||
hideWidgets?: TWorkItemWidgets[];
|
||||
};
|
||||
|
||||
export const IssueDetailWidgets: FC<Props> = (props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled, renderWidgetModals = true } = props;
|
||||
const {
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
disabled,
|
||||
renderWidgetModals = true,
|
||||
issueServiceType,
|
||||
hideWidgets,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-5">
|
||||
@@ -25,16 +41,25 @@ export const IssueDetailWidgets: FC<Props> = (props) => {
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
hideWidgets={hideWidgets}
|
||||
/>
|
||||
<IssueDetailWidgetCollapsibles
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
disabled={disabled}
|
||||
issueServiceType={issueServiceType}
|
||||
hideWidgets={hideWidgets}
|
||||
/>
|
||||
</div>
|
||||
{renderWidgetModals && (
|
||||
<IssueDetailWidgetModals workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} />
|
||||
<IssueDetailWidgetModals
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
issueServiceType={issueServiceType}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { LayersIcon, Plus } from "lucide-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { TIssue, TIssueServiceType } from "@plane/types";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
@@ -13,11 +13,12 @@ type Props = {
|
||||
issueId: string;
|
||||
customButton?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const SubIssuesActionButton: FC<Props> = observer((props) => {
|
||||
const { issueId, customButton, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { issueId, customButton, disabled = false, issueServiceType } = props;
|
||||
// translation
|
||||
const { t } = useTranslation();
|
||||
// store hooks
|
||||
const {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import React, { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
import { Collapsible } from "@plane/ui";
|
||||
// components
|
||||
@@ -14,15 +14,13 @@ type Props = {
|
||||
projectId: string;
|
||||
issueId: string;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const SubIssuesCollapsible: FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
|
||||
const { workspaceSlug, projectId, issueId, disabled = false, issueServiceType } = props;
|
||||
// store hooks
|
||||
const { openWidgets, toggleOpenWidget } = useIssueDetail(issueServiceType);
|
||||
|
||||
// derived state
|
||||
const isCollapsibleOpen = openWidgets.includes("sub-issues");
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { FC, useEffect } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// plane types
|
||||
import type { TIssueLinkEditableFields, TIssueServiceType } from "@plane/types";
|
||||
@@ -24,7 +23,7 @@ export type TIssueLinkCreateEditModal = {
|
||||
isModalOpen: boolean;
|
||||
handleOnClose?: () => void;
|
||||
linkOperations: TLinkOperationsModal;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
const defaultValues: TIssueLinkCreateFormFieldOptions = {
|
||||
@@ -33,10 +32,9 @@ const defaultValues: TIssueLinkCreateFormFieldOptions = {
|
||||
};
|
||||
|
||||
export const IssueLinkCreateUpdateModal: FC<TIssueLinkCreateEditModal> = observer((props) => {
|
||||
const { isModalOpen, handleOnClose, linkOperations, issueServiceType } = props;
|
||||
// i18n
|
||||
const { t } = useTranslation();
|
||||
// props
|
||||
const { isModalOpen, handleOnClose, linkOperations, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
// react hook form
|
||||
const {
|
||||
formState: { errors, isSubmitting },
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
// plane imports
|
||||
import { TIssueServiceType } from "@plane/types";
|
||||
// computed
|
||||
import { useIssueDetail } from "@/hooks/store";
|
||||
// local imports
|
||||
import { IssueLinkItem } from "./link-item";
|
||||
// hooks
|
||||
import { TLinkOperations } from "./root";
|
||||
|
||||
type TLinkOperationsModal = Exclude<TLinkOperations, "create">;
|
||||
@@ -14,12 +14,12 @@ type TLinkList = {
|
||||
issueId: string;
|
||||
linkOperations: TLinkOperationsModal;
|
||||
disabled?: boolean;
|
||||
issueServiceType?: TIssueServiceType;
|
||||
issueServiceType: TIssueServiceType;
|
||||
};
|
||||
|
||||
export const LinkList: FC<TLinkList> = observer((props) => {
|
||||
// props
|
||||
const { issueId, linkOperations, disabled = false, issueServiceType = EIssueServiceType.ISSUES } = props;
|
||||
const { issueId, linkOperations, disabled = false, issueServiceType } = props;
|
||||
// hooks
|
||||
const {
|
||||
link: { getLinksByIssueId },
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
import { FC, useCallback, useMemo, useState } from "react";
|
||||
import { Plus } from "lucide-react";
|
||||
// plane imports
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
import { TIssueLink } from "@plane/types";
|
||||
// hooks
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// hooks
|
||||
import { useIssueDetail } from "@/hooks/store";
|
||||
// ui
|
||||
// components
|
||||
// local imports
|
||||
import { IssueLinkCreateUpdateModal } from "./create-update-link-modal";
|
||||
import { IssueLinkList } from "./links";
|
||||
// types
|
||||
|
||||
export type TLinkOperations = {
|
||||
create: (data: Partial<TIssueLink>) => Promise<void>;
|
||||
@@ -90,7 +90,7 @@ export const IssueLinkRoot: FC<TIssueLinkRoot> = (props) => {
|
||||
title: "Link removed",
|
||||
});
|
||||
toggleIssueLinkModal(false);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
setToast({
|
||||
message: "The link could not be removed",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
@@ -112,6 +112,7 @@ export const IssueLinkRoot: FC<TIssueLinkRoot> = (props) => {
|
||||
isModalOpen={isIssueLinkModal}
|
||||
handleOnClose={handleOnClose}
|
||||
linkOperations={handleLinkOperations}
|
||||
issueServiceType={EIssueServiceType.ISSUES}
|
||||
/>
|
||||
|
||||
<div className="py-1 text-xs">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane imports
|
||||
import { EIssueServiceType } from "@plane/constants";
|
||||
import { EditorRefApi } from "@plane/editor";
|
||||
import { TNameDescriptionLoader } from "@plane/types";
|
||||
// components
|
||||
@@ -179,6 +180,7 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
|
||||
issueId={issueId}
|
||||
disabled={!isEditable || isArchived}
|
||||
renderWidgetModals={!isPeekModeActive}
|
||||
issueServiceType={EIssueServiceType.ISSUES}
|
||||
/>
|
||||
|
||||
{windowSize[0] < 768 && (
|
||||
|
||||
@@ -199,6 +199,7 @@ export const IssueView: FC<IIssueView> = observer((props) => {
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
disabled={disabled || is_archived}
|
||||
issueServiceType={EIssueServiceType.ISSUES}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -238,6 +239,7 @@ export const IssueView: FC<IIssueView> = observer((props) => {
|
||||
projectId={projectId}
|
||||
issueId={issueId}
|
||||
disabled={disabled}
|
||||
issueServiceType={EIssueServiceType.ISSUES}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user