[WEB-756] chore: module and cycle feature toggle validation (#4112)

* chore: cycle and module feature issue block validation

* chore: cycle and module feature display properties validation

* chore: cycle and module feature display filters validation

* chore: cycle and module feature project view validation
This commit is contained in:
Anmol Singh Bhatia 2024-04-03 20:49:02 +05:30 committed by GitHub
parent bc0752f7e8
commit e9518ced89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 144 additions and 59 deletions

View File

@ -10,7 +10,7 @@ import { CustomMenu } from "@plane/ui";
import { ProjectAnalyticsModal } from "@/components/analytics"; import { ProjectAnalyticsModal } from "@/components/analytics";
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues"; import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT, ISSUE_LAYOUTS } from "@/constants/issue"; 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 = () => { export const CycleMobileHeader = () => {
const [analyticsModal, setAnalyticsModal] = useState(false); const [analyticsModal, setAnalyticsModal] = useState(false);
@ -24,6 +24,7 @@ export const CycleMobileHeader = () => {
const { workspaceSlug, projectId, cycleId } = router.query; const { workspaceSlug, projectId, cycleId } = router.query;
const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined; const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined;
// store hooks // store hooks
const { currentProjectDetails } = useProject();
const { const {
issuesFilter: { issueFilters, updateFilters }, issuesFilter: { issueFilters, updateFilters },
} = useIssues(EIssuesStoreType.CYCLE); } = useIssues(EIssuesStoreType.CYCLE);
@ -151,6 +152,8 @@ export const CycleMobileHeader = () => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>
@ -174,6 +177,8 @@ export const CycleMobileHeader = () => {
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
ignoreGroupedFilters={["cycle"]} ignoreGroupedFilters={["cycle"]}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>

View File

@ -250,6 +250,8 @@ export const CycleIssuesHeader: React.FC = observer(() => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end"> <FiltersDropdown title="Display" placement="bottom-end">
@ -262,6 +264,8 @@ export const CycleIssuesHeader: React.FC = observer(() => {
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
ignoreGroupedFilters={["cycle"]} ignoreGroupedFilters={["cycle"]}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>

View File

@ -252,6 +252,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end"> <FiltersDropdown title="Display" placement="bottom-end">
@ -264,6 +266,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
ignoreGroupedFilters={["module"]} ignoreGroupedFilters={["module"]}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>

View File

@ -141,6 +141,8 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end"> <FiltersDropdown title="Display" placement="bottom-end">
@ -152,6 +154,8 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
handleDisplayFiltersUpdate={handleDisplayFilters} handleDisplayFiltersUpdate={handleDisplayFilters}
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>

View File

@ -192,6 +192,8 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end"> <FiltersDropdown title="Display" placement="bottom-end">
@ -203,6 +205,8 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
handleDisplayFiltersUpdate={handleDisplayFilters} handleDisplayFiltersUpdate={handleDisplayFilters}
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>

View File

@ -210,6 +210,8 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end"> <FiltersDropdown title="Display" placement="bottom-end">
@ -221,6 +223,8 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
handleDisplayFiltersUpdate={handleDisplayFilters} handleDisplayFiltersUpdate={handleDisplayFilters}
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
{canUserCreateIssue && ( {canUserCreateIssue && (

View File

@ -9,13 +9,14 @@ import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/com
// constants // constants
import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue"; import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue";
// hooks // hooks
import { useIssues, useLabel, useMember, useProjectState } from "@/hooks/store"; import { useIssues, useLabel, useMember, useProject, useProjectState } from "@/hooks/store";
export const ArchivedIssuesHeader: FC = observer(() => { export const ArchivedIssuesHeader: FC = observer(() => {
// router // router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
// store hooks // store hooks
const { currentProjectDetails } = useProject();
const { const {
issuesFilter: { issueFilters, updateFilters }, issuesFilter: { issueFilters, updateFilters },
} = useIssues(EIssuesStoreType.ARCHIVED); } = useIssues(EIssuesStoreType.ARCHIVED);
@ -89,6 +90,8 @@ export const ArchivedIssuesHeader: FC = observer(() => {
layoutDisplayFiltersOptions={ layoutDisplayFiltersOptions={
activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined activeLayout ? ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues[activeLayout] : undefined
} }
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>

View File

@ -21,6 +21,8 @@ type Props = {
handleDisplayPropertiesUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void; handleDisplayPropertiesUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void;
layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions | undefined; layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions | undefined;
ignoreGroupedFilters?: Partial<TIssueGroupByOptions>[]; ignoreGroupedFilters?: Partial<TIssueGroupByOptions>[];
cycleViewDisabled?: boolean;
moduleViewDisabled?: boolean;
}; };
export const DisplayFiltersSelection: React.FC<Props> = observer((props) => { export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
@ -31,17 +33,32 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
handleDisplayPropertiesUpdate, handleDisplayPropertiesUpdate,
layoutDisplayFiltersOptions, layoutDisplayFiltersOptions,
ignoreGroupedFilters = [], ignoreGroupedFilters = [],
cycleViewDisabled = false,
moduleViewDisabled = false,
} = props; } = props;
const isDisplayFilterEnabled = (displayFilter: keyof IIssueDisplayFilterOptions) => const isDisplayFilterEnabled = (displayFilter: keyof IIssueDisplayFilterOptions) =>
Object.keys(layoutDisplayFiltersOptions?.display_filters ?? {}).includes(displayFilter); Object.keys(layoutDisplayFiltersOptions?.display_filters ?? {}).includes(displayFilter);
const computedIgnoreGroupedFilters: Partial<TIssueGroupByOptions>[] = [];
if (cycleViewDisabled) {
ignoreGroupedFilters.push("cycle");
}
if (moduleViewDisabled) {
ignoreGroupedFilters.push("module");
}
return ( return (
<div className="vertical-scrollbar scrollbar-sm relative h-full w-full divide-y divide-custom-border-200 overflow-hidden overflow-y-auto px-2.5"> <div className="vertical-scrollbar scrollbar-sm relative h-full w-full divide-y divide-custom-border-200 overflow-hidden overflow-y-auto px-2.5">
{/* display properties */} {/* display properties */}
{layoutDisplayFiltersOptions?.display_properties && ( {layoutDisplayFiltersOptions?.display_properties && (
<div className="py-2"> <div className="py-2">
<FilterDisplayProperties displayProperties={displayProperties} handleUpdate={handleDisplayPropertiesUpdate} /> <FilterDisplayProperties
displayProperties={displayProperties}
handleUpdate={handleDisplayPropertiesUpdate}
cycleViewDisabled={cycleViewDisabled}
moduleViewDisabled={moduleViewDisabled}
/>
</div> </div>
)} )}
@ -56,7 +73,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
group_by: val, group_by: val,
}) })
} }
ignoreGroupedFilters={ignoreGroupedFilters} ignoreGroupedFilters={[...ignoreGroupedFilters, ...computedIgnoreGroupedFilters]}
/> />
</div> </div>
)} )}
@ -74,7 +91,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
}) })
} }
subGroupByOptions={layoutDisplayFiltersOptions?.display_filters.sub_group_by ?? []} subGroupByOptions={layoutDisplayFiltersOptions?.display_filters.sub_group_by ?? []}
ignoreGroupedFilters={ignoreGroupedFilters} ignoreGroupedFilters={[...ignoreGroupedFilters, ...computedIgnoreGroupedFilters]}
/> />
</div> </div>
)} )}

View File

@ -10,13 +10,22 @@ import { FilterHeader } from "../helpers/filter-header";
type Props = { type Props = {
displayProperties: IIssueDisplayProperties; displayProperties: IIssueDisplayProperties;
handleUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void; handleUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void;
cycleViewDisabled?: boolean;
moduleViewDisabled?: boolean;
}; };
export const FilterDisplayProperties: React.FC<Props> = observer((props) => { export const FilterDisplayProperties: React.FC<Props> = observer((props) => {
const { displayProperties, handleUpdate } = props; const { displayProperties, handleUpdate, cycleViewDisabled = false, moduleViewDisabled = false } = props;
const [previewEnabled, setPreviewEnabled] = React.useState(true); 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 ( return (
<> <>
<FilterHeader <FilterHeader
@ -26,23 +35,25 @@ export const FilterDisplayProperties: React.FC<Props> = observer((props) => {
/> />
{previewEnabled && ( {previewEnabled && (
<div className="mt-1 flex flex-wrap items-center gap-2"> <div className="mt-1 flex flex-wrap items-center gap-2">
{ISSUE_DISPLAY_PROPERTIES.map((displayProperty) => ( {filteredDisplayProperties.map((displayProperty) => (
<button <>
key={displayProperty.key} <button
type="button" key={displayProperty.key}
className={`rounded border px-2 py-0.5 text-xs transition-all ${ type="button"
displayProperties?.[displayProperty.key] className={`rounded border px-2 py-0.5 text-xs transition-all ${
? "border-custom-primary-100 bg-custom-primary-100 text-white" displayProperties?.[displayProperty.key]
: "border-custom-border-200 hover:bg-custom-background-80" ? "border-custom-primary-100 bg-custom-primary-100 text-white"
}`} : "border-custom-border-200 hover:bg-custom-background-80"
onClick={() => }`}
handleUpdate({ onClick={() =>
[displayProperty.key]: !displayProperties?.[displayProperty.key], handleUpdate({
}) [displayProperty.key]: !displayProperties?.[displayProperty.key],
} })
> }
{displayProperty.title} >
</button> {displayProperty.title}
</button>
</>
))} ))}
</div> </div>
)} )}

View File

@ -30,10 +30,21 @@ type Props = {
labels?: IIssueLabel[] | undefined; labels?: IIssueLabel[] | undefined;
memberIds?: string[] | undefined; memberIds?: string[] | undefined;
states?: IState[] | undefined; states?: IState[] | undefined;
cycleViewDisabled?: boolean;
moduleViewDisabled?: boolean;
}; };
export const FilterSelection: React.FC<Props> = observer((props) => { export const FilterSelection: React.FC<Props> = observer((props) => {
const { filters, handleFiltersUpdate, layoutDisplayFiltersOptions, labels, memberIds, states } = props; const {
filters,
handleFiltersUpdate,
layoutDisplayFiltersOptions,
labels,
memberIds,
states,
cycleViewDisabled = false,
moduleViewDisabled = false,
} = props;
// hooks // hooks
const { const {
router: { moduleId, cycleId }, router: { moduleId, cycleId },
@ -111,7 +122,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
)} )}
{/* cycle */} {/* cycle */}
{isFilterEnabled("cycle") && !cycleId && ( {isFilterEnabled("cycle") && !cycleId && !cycleViewDisabled && (
<div className="py-2"> <div className="py-2">
<FilterCycle <FilterCycle
appliedFilters={filters.cycle ?? null} appliedFilters={filters.cycle ?? null}
@ -122,7 +133,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
)} )}
{/* module */} {/* module */}
{isFilterEnabled("module") && !moduleId && ( {isFilterEnabled("module") && !moduleId && !moduleViewDisabled && (
<div className="py-2"> <div className="py-2">
<FilterModule <FilterModule
appliedFilters={filters.module ?? null} appliedFilters={filters.module ?? null}

View File

@ -24,7 +24,7 @@ import { EIssuesStoreType } from "@/constants/issue";
import { cn } from "@/helpers/common.helper"; import { cn } from "@/helpers/common.helper";
import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper"; import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "@/helpers/issue.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"; import { usePlatformOS } from "@/hooks/use-platform-os";
// components // components
import { IssuePropertyLabels } from "../properties/labels"; import { IssuePropertyLabels } from "../properties/labels";
@ -45,6 +45,7 @@ export interface IIssueProperties {
export const IssueProperties: React.FC<IIssueProperties> = observer((props) => { export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
const { issue, updateIssue, displayProperties, activeLayout, isReadOnly, className } = props; const { issue, updateIssue, displayProperties, activeLayout, isReadOnly, className } = props;
// store hooks // store hooks
const { getProjectById } = useProject();
const { labelMap } = useLabel(); const { labelMap } = useLabel();
const { captureIssueEvent } = useEventTracker(); const { captureIssueEvent } = useEventTracker();
const { const {
@ -56,6 +57,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
const { areEstimatesEnabledForCurrentProject } = useEstimate(); const { areEstimatesEnabledForCurrentProject } = useEstimate();
const { getStateById } = useProjectState(); const { getStateById } = useProjectState();
const { isMobile } = usePlatformOS(); const { isMobile } = usePlatformOS();
const projectDetails = getProjectById(issue.project_id);
// router // router
const router = useRouter(); const router = useRouter();
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
@ -349,36 +351,40 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
</WithDisplayPropertiesHOC> </WithDisplayPropertiesHOC>
{/* modules */} {/* modules */}
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="modules"> {projectDetails?.module_view && (
<div className="h-5"> <WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="modules">
<ModuleDropdown <div className="h-5">
buttonContainerClassName="truncate max-w-40" <ModuleDropdown
projectId={issue?.project_id} buttonContainerClassName="truncate max-w-40"
value={issue?.module_ids ?? []} projectId={issue?.project_id}
onChange={handleModule} value={issue?.module_ids ?? []}
disabled={isReadOnly} onChange={handleModule}
multiple disabled={isReadOnly}
buttonVariant="border-with-text" multiple
showCount buttonVariant="border-with-text"
showTooltip showCount
/> showTooltip
</div> />
</WithDisplayPropertiesHOC> </div>
</WithDisplayPropertiesHOC>
)}
{/* cycles */} {/* cycles */}
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="cycle"> {projectDetails?.cycle_view && (
<div className="h-5"> <WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="cycle">
<CycleDropdown <div className="h-5">
buttonContainerClassName="truncate max-w-40" <CycleDropdown
projectId={issue?.project_id} buttonContainerClassName="truncate max-w-40"
value={issue?.cycle_id} projectId={issue?.project_id}
onChange={handleCycle} value={issue?.cycle_id}
disabled={isReadOnly} onChange={handleCycle}
buttonVariant="border-with-text" disabled={isReadOnly}
showTooltip buttonVariant="border-with-text"
/> showTooltip
</div> />
</WithDisplayPropertiesHOC> </div>
</WithDisplayPropertiesHOC>
)}
{/* estimates */} {/* estimates */}
{areEstimatesEnabledForCurrentProject && ( {areEstimatesEnabledForCurrentProject && (

View File

@ -132,6 +132,8 @@ export const IssuesMobileHeader = observer(() => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>
@ -154,6 +156,8 @@ export const IssuesMobileHeader = observer(() => {
handleDisplayFiltersUpdate={handleDisplayFilters} handleDisplayFiltersUpdate={handleDisplayFilters}
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>

View File

@ -11,12 +11,13 @@ import { ProjectAnalyticsModal } from "@/components/analytics";
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues"; import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
// hooks // hooks
import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT, ISSUE_LAYOUTS } from "@/constants/issue"; 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 // types
// constants // constants
export const ModuleMobileHeader = observer(() => { export const ModuleMobileHeader = observer(() => {
const [analyticsModal, setAnalyticsModal] = useState(false); const [analyticsModal, setAnalyticsModal] = useState(false);
const { currentProjectDetails } = useProject();
const { getModuleById } = useModule(); const { getModuleById } = useModule();
const layouts = [ const layouts = [
{ key: "list", title: "List", icon: List }, { key: "list", title: "List", icon: List },
@ -134,6 +135,8 @@ export const ModuleMobileHeader = observer(() => {
labels={projectLabels} labels={projectLabels}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>
@ -157,6 +160,8 @@ export const ModuleMobileHeader = observer(() => {
displayProperties={issueFilters?.displayProperties ?? {}} displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties} handleDisplayPropertiesUpdate={handleDisplayProperties}
ignoreGroupedFilters={["module"]} ignoreGroupedFilters={["module"]}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
</div> </div>

View File

@ -6,7 +6,7 @@ import { IProjectView, IIssueFilterOptions } from "@plane/types";
import { Button, Input, TextArea } from "@plane/ui"; import { Button, Input, TextArea } from "@plane/ui";
import { AppliedFiltersList, FilterSelection, FiltersDropdown } from "@/components/issues"; import { AppliedFiltersList, FilterSelection, FiltersDropdown } from "@/components/issues";
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue"; 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 // components
// ui // ui
// types // types
@ -27,6 +27,7 @@ const defaultValues: Partial<IProjectView> = {
export const ProjectViewForm: React.FC<Props> = observer((props) => { export const ProjectViewForm: React.FC<Props> = observer((props) => {
const { handleFormSubmit, handleClose, data, preLoadedData } = props; const { handleFormSubmit, handleClose, data, preLoadedData } = props;
// store hooks // store hooks
const { currentProjectDetails } = useProject();
const { projectStates } = useProjectState(); const { projectStates } = useProjectState();
const { projectLabels } = useLabel(); const { projectLabels } = useLabel();
const { const {
@ -184,6 +185,8 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
labels={projectLabels ?? undefined} labels={projectLabels ?? undefined}
memberIds={projectMemberIds ?? undefined} memberIds={projectMemberIds ?? undefined}
states={projectStates} states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/> />
</FiltersDropdown> </FiltersDropdown>
)} )}
@ -212,8 +215,8 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
? "Updating View..." ? "Updating View..."
: "Update View" : "Update View"
: isSubmitting : isSubmitting
? "Creating View..." ? "Creating View..."
: "Create View"} : "Create View"}
</Button> </Button>
</div> </div>
</form> </form>