+
{displayProperties && displayProperties?.key && (
diff --git a/web/components/issues/issue-layouts/properties/all-properties.tsx b/web/components/issues/issue-layouts/properties/all-properties.tsx
index 72614079a2..ab1cad738b 100644
--- a/web/components/issues/issue-layouts/properties/all-properties.tsx
+++ b/web/components/issues/issue-layouts/properties/all-properties.tsx
@@ -24,7 +24,7 @@ import { EIssuesStoreType } from "@/constants/issue";
import { cn } from "@/helpers/common.helper";
import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper";
-import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState } from "@/hooks/store";
+import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState, useProject } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
// components
import { IssuePropertyLabels } from "../properties/labels";
@@ -45,6 +45,7 @@ export interface IIssueProperties {
export const IssueProperties: React.FC
= observer((props) => {
const { issue, updateIssue, displayProperties, activeLayout, isReadOnly, className } = props;
// store hooks
+ const { getProjectById } = useProject();
const { labelMap } = useLabel();
const { captureIssueEvent } = useEventTracker();
const {
@@ -56,6 +57,7 @@ export const IssueProperties: React.FC = observer((props) => {
const { areEstimatesEnabledForCurrentProject } = useEstimate();
const { getStateById } = useProjectState();
const { isMobile } = usePlatformOS();
+ const projectDetails = getProjectById(issue.project_id);
// router
const router = useRouter();
const { workspaceSlug } = router.query;
@@ -349,36 +351,40 @@ export const IssueProperties: React.FC = observer((props) => {
{/* modules */}
-
-
-
-
-
+ {projectDetails?.module_view && (
+
+
+
+
+
+ )}
{/* cycles */}
-
-
-
-
-
+ {projectDetails?.cycle_view && (
+
+
+
+
+
+ )}
{/* estimates */}
{areEstimatesEnabledForCurrentProject && (
diff --git a/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx b/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx
index d996ee5988..8a49ec9b47 100644
--- a/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx
+++ b/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx
@@ -1,22 +1,23 @@
import { useState } from "react";
+import { observer } from "mobx-react";
import { useRouter } from "next/router";
+// icons
import { ArchiveRestoreIcon, ExternalLink, Link, Trash2 } from "lucide-react";
-// hooks
-import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
-
-import { DeleteIssueModal } from "@/components/issues";
// ui
+import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
// components
+import { DeleteIssueModal } from "@/components/issues";
+// constants
import { EIssuesStoreType } from "@/constants/issue";
import { EUserProjectRoles } from "@/constants/project";
-import { copyUrlToClipboard } from "@/helpers/string.helper";
-import { useEventTracker, useIssues, useUser } from "@/hooks/store";
-// components
// helpers
+import { copyUrlToClipboard } from "@/helpers/string.helper";
+// hooks
+import { useEventTracker, useIssues, useUser } from "@/hooks/store";
// types
import { IQuickActionProps } from "../list/list-view-types";
-export const ArchivedIssueQuickActions: React.FC = (props) => {
+export const ArchivedIssueQuickActions: React.FC = observer((props) => {
const { issue, handleDelete, handleRestore, customActionButton, portalElement, readOnly = false } = props;
// states
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
@@ -46,6 +47,24 @@ export const ArchivedIssueQuickActions: React.FC = (props) =>
message: "Issue link copied to clipboard",
})
);
+ const handleIssueRestore = async () => {
+ if (!handleRestore) return;
+ await handleRestore()
+ .then(() => {
+ setToast({
+ type: TOAST_TYPE.SUCCESS,
+ title: "Restore success",
+ message: "Your issue can be found in project issues.",
+ });
+ })
+ .catch(() => {
+ setToast({
+ type: TOAST_TYPE.ERROR,
+ title: "Error!",
+ message: "Issue could not be restored. Please try again.",
+ });
+ });
+ };
return (
<>
@@ -65,7 +84,7 @@ export const ArchivedIssueQuickActions: React.FC = (props) =>
ellipsis
>
{isRestoringAllowed && (
-
+
Restore
@@ -100,4 +119,4 @@ export const ArchivedIssueQuickActions: React.FC
= (props) =>
>
);
-};
+});
diff --git a/web/components/issues/issue-modal/form.tsx b/web/components/issues/issue-modal/form.tsx
index 6112a27fea..88d6c38778 100644
--- a/web/components/issues/issue-modal/form.tsx
+++ b/web/components/issues/issue-modal/form.tsx
@@ -327,32 +327,38 @@ export const IssueFormRoot: FC = observer((props) => {
{watch("parent_id") && selectedParentIssue && (
-
-
-
-
- {selectedParentIssue.project__identifier}-{selectedParentIssue.sequence_id}
-
- {selectedParentIssue.name.substring(0, 50)}
-
-
-
+ (
+
+
+
+
+ {selectedParentIssue.project__identifier}-{selectedParentIssue.sequence_id}
+
+ {selectedParentIssue.name.substring(0, 50)}
+
+
+
+ )}
+ />
)}
@@ -535,7 +541,7 @@ export const IssueFormRoot: FC
= observer((props) => {
handleFormChange();
}}
buttonVariant={value?.length > 0 ? "transparent-without-text" : "border-with-text"}
- buttonClassName={value?.length > 0 ? "hover:bg-transparent px-0" : ""}
+ buttonClassName={value?.length > 0 ? "hover:bg-transparent" : ""}
placeholder="Assignees"
multiple
tabIndex={getTabIndex("assignee_ids")}
@@ -657,33 +663,23 @@ export const IssueFormRoot: FC = observer((props) => {
)}
/>
)}
-
- {watch("parent_id") ? (
-
-
-
- {selectedParentIssue &&
- `${selectedParentIssue.project__identifier}-
- ${selectedParentIssue.sequence_id}`}
-
-
- ) : (
-
-
- Add parent
-
- )}
-
- }
- placement="bottom-start"
- tabIndex={getTabIndex("parent_id")}
- >
- {watch("parent_id") ? (
+ {watch("parent_id") ? (
+
+
+
+ {selectedParentIssue &&
+ `${selectedParentIssue.project__identifier}-${selectedParentIssue.sequence_id}`}
+
+
+ }
+ placement="bottom-start"
+ tabIndex={getTabIndex("parent_id")}
+ >
<>
setParentIssueListModalOpen(true)}>
Change parent issue
@@ -698,12 +694,17 @@ export const IssueFormRoot: FC = observer((props) => {
Remove parent issue
>
- ) : (
- setParentIssueListModalOpen(true)}>
- Select parent Issue
-
- )}
-
+
+ ) : (
+
+ )}
{
labels={projectLabels}
memberIds={projectMemberIds ?? undefined}
states={projectStates}
+ cycleViewDisabled={!currentProjectDetails?.cycle_view}
+ moduleViewDisabled={!currentProjectDetails?.module_view}
/>
@@ -154,6 +156,8 @@ export const IssuesMobileHeader = observer(() => {
handleDisplayFiltersUpdate={handleDisplayFilters}
displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties}
+ cycleViewDisabled={!currentProjectDetails?.cycle_view}
+ moduleViewDisabled={!currentProjectDetails?.module_view}
/>
diff --git a/web/components/issues/peek-overview/issue-detail.tsx b/web/components/issues/peek-overview/issue-detail.tsx
index b3dd7808e5..ab84dc3c0f 100644
--- a/web/components/issues/peek-overview/issue-detail.tsx
+++ b/web/components/issues/peek-overview/issue-detail.tsx
@@ -87,6 +87,7 @@ export const PeekOverviewIssueDetails: FC = observer(
projectId={issue.project_id}
issueId={issueId}
currentUser={currentUser}
+ disabled={disabled}
/>
)}
diff --git a/web/components/issues/peek-overview/root.tsx b/web/components/issues/peek-overview/root.tsx
index a7f7b23d7a..4d85bd73cd 100644
--- a/web/components/issues/peek-overview/root.tsx
+++ b/web/components/issues/peek-overview/root.tsx
@@ -135,22 +135,12 @@ export const IssuePeekOverview: FC
= observer((props) => {
archive: async (workspaceSlug: string, projectId: string, issueId: string) => {
try {
await archiveIssue(workspaceSlug, projectId, issueId);
- setToast({
- type: TOAST_TYPE.SUCCESS,
- title: "Success!",
- message: "Issue archived successfully.",
- });
captureIssueEvent({
eventName: ISSUE_ARCHIVED,
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
path: router.asPath,
});
} catch (error) {
- setToast({
- type: TOAST_TYPE.ERROR,
- title: "Error!",
- message: "Issue could not be archived. Please try again.",
- });
captureIssueEvent({
eventName: ISSUE_ARCHIVED,
payload: { id: issueId, state: "FAILED", element: "Issue peek-overview" },
@@ -163,8 +153,8 @@ export const IssuePeekOverview: FC = observer((props) => {
await restoreIssue(workspaceSlug, projectId, issueId);
setToast({
type: TOAST_TYPE.SUCCESS,
- title: "Success!",
- message: "Issue restored successfully.",
+ title: "Restore success",
+ message: "Your issue can be found in project issues.",
});
captureIssueEvent({
eventName: ISSUE_RESTORED,
diff --git a/web/components/issues/peek-overview/view.tsx b/web/components/issues/peek-overview/view.tsx
index 35925d6cd5..0366fbb61d 100644
--- a/web/components/issues/peek-overview/view.tsx
+++ b/web/components/issues/peek-overview/view.tsx
@@ -177,7 +177,12 @@ export const IssueView: FC = observer((props) => {
disabled={disabled || is_archived}
/>
-
+
) : (
@@ -210,7 +215,12 @@ export const IssueView: FC = observer((props) => {
workspaceSlug={workspaceSlug}
/>
-
+
= (props) => {
message: "Your archives can be found in project archives.",
});
onClose();
- router.push(`/${workspaceSlug}/projects/${projectId}/archives/modules?peekModule=${moduleId}`);
+ router.push(`/${workspaceSlug}/projects/${projectId}/modules`);
})
.catch(() =>
setToast({
diff --git a/web/components/modules/module-mobile-header.tsx b/web/components/modules/module-mobile-header.tsx
index 6419b13b08..79486a37cc 100644
--- a/web/components/modules/module-mobile-header.tsx
+++ b/web/components/modules/module-mobile-header.tsx
@@ -11,12 +11,13 @@ import { ProjectAnalyticsModal } from "@/components/analytics";
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
// hooks
import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT, ISSUE_LAYOUTS } from "@/constants/issue";
-import { useIssues, useLabel, useMember, useModule, useProjectState } from "@/hooks/store";
+import { useIssues, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
// types
// constants
export const ModuleMobileHeader = observer(() => {
const [analyticsModal, setAnalyticsModal] = useState(false);
+ const { currentProjectDetails } = useProject();
const { getModuleById } = useModule();
const layouts = [
{ key: "list", title: "List", icon: List },
@@ -134,6 +135,8 @@ export const ModuleMobileHeader = observer(() => {
labels={projectLabels}
memberIds={projectMemberIds ?? undefined}
states={projectStates}
+ cycleViewDisabled={!currentProjectDetails?.cycle_view}
+ moduleViewDisabled={!currentProjectDetails?.module_view}
/>
@@ -157,6 +160,8 @@ export const ModuleMobileHeader = observer(() => {
displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties}
ignoreGroupedFilters={["module"]}
+ cycleViewDisabled={!currentProjectDetails?.cycle_view}
+ moduleViewDisabled={!currentProjectDetails?.module_view}
/>
diff --git a/web/components/modules/quick-actions.tsx b/web/components/modules/quick-actions.tsx
index b7972d6124..5decec4ecc 100644
--- a/web/components/modules/quick-actions.tsx
+++ b/web/components/modules/quick-actions.tsx
@@ -79,7 +79,7 @@ export const ModuleQuickActions: React.FC