diff --git a/web/components/cycles/cycle-mobile-header.tsx b/web/components/cycles/cycle-mobile-header.tsx index 8c168cbaa08..54a2a311503 100644 --- a/web/components/cycles/cycle-mobile-header.tsx +++ b/web/components/cycles/cycle-mobile-header.tsx @@ -10,7 +10,7 @@ import { CustomMenu } from "@plane/ui"; import { ProjectAnalyticsModal } from "@/components/analytics"; import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues"; import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT, ISSUE_LAYOUTS } from "@/constants/issue"; -import { useIssues, useCycle, useProjectState, useLabel, useMember } from "@/hooks/store"; +import { useIssues, useCycle, useProjectState, useLabel, useMember, useProject } from "@/hooks/store"; export const CycleMobileHeader = () => { const [analyticsModal, setAnalyticsModal] = useState(false); @@ -24,6 +24,7 @@ export const CycleMobileHeader = () => { const { workspaceSlug, projectId, cycleId } = router.query; const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined; // store hooks + const { currentProjectDetails } = useProject(); const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.CYCLE); @@ -151,6 +152,8 @@ export const CycleMobileHeader = () => { labels={projectLabels} memberIds={projectMemberIds ?? undefined} states={projectStates} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> @@ -174,6 +177,8 @@ export const CycleMobileHeader = () => { displayProperties={issueFilters?.displayProperties ?? {}} handleDisplayPropertiesUpdate={handleDisplayProperties} ignoreGroupedFilters={["cycle"]} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> diff --git a/web/components/headers/cycle-issues.tsx b/web/components/headers/cycle-issues.tsx index 35a646c1c95..e1113910f68 100644 --- a/web/components/headers/cycle-issues.tsx +++ b/web/components/headers/cycle-issues.tsx @@ -250,6 +250,8 @@ export const CycleIssuesHeader: React.FC = observer(() => { labels={projectLabels} memberIds={projectMemberIds ?? undefined} states={projectStates} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> @@ -262,6 +264,8 @@ export const CycleIssuesHeader: React.FC = observer(() => { displayProperties={issueFilters?.displayProperties ?? {}} handleDisplayPropertiesUpdate={handleDisplayProperties} ignoreGroupedFilters={["cycle"]} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> diff --git a/web/components/headers/module-issues.tsx b/web/components/headers/module-issues.tsx index 59cc2a42955..56da66d2fdf 100644 --- a/web/components/headers/module-issues.tsx +++ b/web/components/headers/module-issues.tsx @@ -252,6 +252,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => { labels={projectLabels} memberIds={projectMemberIds ?? undefined} states={projectStates} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> @@ -264,6 +266,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => { displayProperties={issueFilters?.displayProperties ?? {}} handleDisplayPropertiesUpdate={handleDisplayProperties} ignoreGroupedFilters={["module"]} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> diff --git a/web/components/headers/project-draft-issues.tsx b/web/components/headers/project-draft-issues.tsx index bdfaebc8de7..a9f5a93f746 100644 --- a/web/components/headers/project-draft-issues.tsx +++ b/web/components/headers/project-draft-issues.tsx @@ -141,6 +141,8 @@ export const ProjectDraftIssueHeader: FC = observer(() => { labels={projectLabels} memberIds={projectMemberIds ?? undefined} states={projectStates} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> @@ -152,6 +154,8 @@ export const ProjectDraftIssueHeader: FC = observer(() => { handleDisplayFiltersUpdate={handleDisplayFilters} displayProperties={issueFilters?.displayProperties ?? {}} handleDisplayPropertiesUpdate={handleDisplayProperties} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> diff --git a/web/components/headers/project-issues.tsx b/web/components/headers/project-issues.tsx index 7c018d5c2fe..fd681cc4ad6 100644 --- a/web/components/headers/project-issues.tsx +++ b/web/components/headers/project-issues.tsx @@ -192,6 +192,8 @@ export const ProjectIssuesHeader: React.FC = observer(() => { labels={projectLabels} memberIds={projectMemberIds ?? undefined} states={projectStates} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> @@ -203,6 +205,8 @@ export const ProjectIssuesHeader: React.FC = observer(() => { handleDisplayFiltersUpdate={handleDisplayFilters} displayProperties={issueFilters?.displayProperties ?? {}} handleDisplayPropertiesUpdate={handleDisplayProperties} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> diff --git a/web/components/headers/project-view-issues.tsx b/web/components/headers/project-view-issues.tsx index 6f545f25b1a..27c6e5f9dcc 100644 --- a/web/components/headers/project-view-issues.tsx +++ b/web/components/headers/project-view-issues.tsx @@ -210,6 +210,8 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { labels={projectLabels} memberIds={projectMemberIds ?? undefined} states={projectStates} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> @@ -221,6 +223,8 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => { handleDisplayFiltersUpdate={handleDisplayFilters} displayProperties={issueFilters?.displayProperties ?? {}} handleDisplayPropertiesUpdate={handleDisplayProperties} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> {canUserCreateIssue && ( diff --git a/web/components/issues/archived-issues-header.tsx b/web/components/issues/archived-issues-header.tsx index cd5aca903c8..bf8c373323c 100644 --- a/web/components/issues/archived-issues-header.tsx +++ b/web/components/issues/archived-issues-header.tsx @@ -9,13 +9,14 @@ import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/com // constants import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue"; // hooks -import { useIssues, useLabel, useMember, useProjectState } from "@/hooks/store"; +import { useIssues, useLabel, useMember, useProject, useProjectState } from "@/hooks/store"; export const ArchivedIssuesHeader: FC = observer(() => { // router const router = useRouter(); const { workspaceSlug, projectId } = router.query; // store hooks + const { currentProjectDetails } = useProject(); const { issuesFilter: { issueFilters, updateFilters }, } = useIssues(EIssuesStoreType.ARCHIVED); @@ -89,6 +90,8 @@ export const ArchivedIssuesHeader: FC = observer(() => { layoutDisplayFiltersOptions={ activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined } + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> diff --git a/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx b/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx index d270d6a1ccd..eb2238a4b95 100644 --- a/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx +++ b/web/components/issues/issue-layouts/filters/header/display-filters/display-filters-selection.tsx @@ -21,6 +21,8 @@ type Props = { handleDisplayPropertiesUpdate: (updatedDisplayProperties: Partial) => void; layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions | undefined; ignoreGroupedFilters?: Partial[]; + cycleViewDisabled?: boolean; + moduleViewDisabled?: boolean; }; export const DisplayFiltersSelection: React.FC = observer((props) => { @@ -31,17 +33,32 @@ export const DisplayFiltersSelection: React.FC = observer((props) => { handleDisplayPropertiesUpdate, layoutDisplayFiltersOptions, ignoreGroupedFilters = [], + cycleViewDisabled = false, + moduleViewDisabled = false, } = props; const isDisplayFilterEnabled = (displayFilter: keyof IIssueDisplayFilterOptions) => Object.keys(layoutDisplayFiltersOptions?.display_filters ?? {}).includes(displayFilter); + const computedIgnoreGroupedFilters: Partial[] = []; + if (cycleViewDisabled) { + ignoreGroupedFilters.push("cycle"); + } + if (moduleViewDisabled) { + ignoreGroupedFilters.push("module"); + } + return (
{/* display properties */} {layoutDisplayFiltersOptions?.display_properties && (
- +
)} @@ -56,7 +73,7 @@ export const DisplayFiltersSelection: React.FC = observer((props) => { group_by: val, }) } - ignoreGroupedFilters={ignoreGroupedFilters} + ignoreGroupedFilters={[...ignoreGroupedFilters, ...computedIgnoreGroupedFilters]} />
)} @@ -74,7 +91,7 @@ export const DisplayFiltersSelection: React.FC = observer((props) => { }) } subGroupByOptions={layoutDisplayFiltersOptions?.display_filters.sub_group_by ?? []} - ignoreGroupedFilters={ignoreGroupedFilters} + ignoreGroupedFilters={[...ignoreGroupedFilters, ...computedIgnoreGroupedFilters]} /> )} diff --git a/web/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx b/web/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx index 54cb0a439d8..aebb8d5cc11 100644 --- a/web/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx +++ b/web/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx @@ -10,13 +10,22 @@ import { FilterHeader } from "../helpers/filter-header"; type Props = { displayProperties: IIssueDisplayProperties; handleUpdate: (updatedDisplayProperties: Partial) => void; + cycleViewDisabled?: boolean; + moduleViewDisabled?: boolean; }; export const FilterDisplayProperties: React.FC = observer((props) => { - const { displayProperties, handleUpdate } = props; + const { displayProperties, handleUpdate, cycleViewDisabled = false, moduleViewDisabled = false } = props; const [previewEnabled, setPreviewEnabled] = React.useState(true); + // Filter out "cycle" and "module" keys if cycleViewDisabled or moduleViewDisabled is true + const filteredDisplayProperties = ISSUE_DISPLAY_PROPERTIES.filter((property) => { + if (cycleViewDisabled && property.key === "cycle") return false; + if (moduleViewDisabled && property.key === "modules") return false; + return true; + }); + return ( <> = observer((props) => { /> {previewEnabled && (
- {ISSUE_DISPLAY_PROPERTIES.map((displayProperty) => ( - + {filteredDisplayProperties.map((displayProperty) => ( + <> + + ))}
)} diff --git a/web/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx b/web/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx index 7e6e44ebf2e..9220e9fd31e 100644 --- a/web/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx +++ b/web/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx @@ -30,10 +30,21 @@ type Props = { labels?: IIssueLabel[] | undefined; memberIds?: string[] | undefined; states?: IState[] | undefined; + cycleViewDisabled?: boolean; + moduleViewDisabled?: boolean; }; export const FilterSelection: React.FC = observer((props) => { - const { filters, handleFiltersUpdate, layoutDisplayFiltersOptions, labels, memberIds, states } = props; + const { + filters, + handleFiltersUpdate, + layoutDisplayFiltersOptions, + labels, + memberIds, + states, + cycleViewDisabled = false, + moduleViewDisabled = false, + } = props; // hooks const { router: { moduleId, cycleId }, @@ -111,7 +122,7 @@ export const FilterSelection: React.FC = observer((props) => { )} {/* cycle */} - {isFilterEnabled("cycle") && !cycleId && ( + {isFilterEnabled("cycle") && !cycleId && !cycleViewDisabled && (
= observer((props) => { )} {/* module */} - {isFilterEnabled("module") && !moduleId && ( + {isFilterEnabled("module") && !moduleId && !moduleViewDisabled && (
= 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/issues-mobile-header.tsx b/web/components/issues/issues-mobile-header.tsx index 4bc90b686c0..de1c088e047 100644 --- a/web/components/issues/issues-mobile-header.tsx +++ b/web/components/issues/issues-mobile-header.tsx @@ -132,6 +132,8 @@ export const IssuesMobileHeader = observer(() => { 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/modules/module-mobile-header.tsx b/web/components/modules/module-mobile-header.tsx index 6419b13b08c..79486a37cc5 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/views/form.tsx b/web/components/views/form.tsx index e758b7938ae..a8fa6b87cb9 100644 --- a/web/components/views/form.tsx +++ b/web/components/views/form.tsx @@ -6,7 +6,7 @@ import { IProjectView, IIssueFilterOptions } from "@plane/types"; import { Button, Input, TextArea } from "@plane/ui"; import { AppliedFiltersList, FilterSelection, FiltersDropdown } from "@/components/issues"; import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue"; -import { useLabel, useMember, useProjectState } from "@/hooks/store"; +import { useLabel, useMember, useProject, useProjectState } from "@/hooks/store"; // components // ui // types @@ -27,6 +27,7 @@ const defaultValues: Partial = { export const ProjectViewForm: React.FC = observer((props) => { const { handleFormSubmit, handleClose, data, preLoadedData } = props; // store hooks + const { currentProjectDetails } = useProject(); const { projectStates } = useProjectState(); const { projectLabels } = useLabel(); const { @@ -184,6 +185,8 @@ export const ProjectViewForm: React.FC = observer((props) => { labels={projectLabels ?? undefined} memberIds={projectMemberIds ?? undefined} states={projectStates} + cycleViewDisabled={!currentProjectDetails?.cycle_view} + moduleViewDisabled={!currentProjectDetails?.module_view} /> )} @@ -212,8 +215,8 @@ export const ProjectViewForm: React.FC = observer((props) => { ? "Updating View..." : "Update View" : isSubmitting - ? "Creating View..." - : "Create View"} + ? "Creating View..." + : "Create View"}