Skip to content

Commit

Permalink
[WEB-756] chore: module and cycle feature toggle validation (#4112)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
anmolsinghbhatia committed Apr 3, 2024
1 parent bc0752f commit e9518ce
Show file tree
Hide file tree
Showing 14 changed files with 144 additions and 59 deletions.
7 changes: 6 additions & 1 deletion web/components/cycles/cycle-mobile-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -151,6 +152,8 @@ export const CycleMobileHeader = () => {
labels={projectLabels}
memberIds={projectMemberIds ?? undefined}
states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/>
</FiltersDropdown>
</div>
Expand All @@ -174,6 +177,8 @@ export const CycleMobileHeader = () => {
displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties}
ignoreGroupedFilters={["cycle"]}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/>
</FiltersDropdown>
</div>
Expand Down
4 changes: 4 additions & 0 deletions web/components/headers/cycle-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
/>
</FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end">
Expand All @@ -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}
/>
</FiltersDropdown>

Expand Down
4 changes: 4 additions & 0 deletions web/components/headers/module-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
/>
</FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end">
Expand All @@ -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}
/>
</FiltersDropdown>
</div>
Expand Down
4 changes: 4 additions & 0 deletions web/components/headers/project-draft-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
labels={projectLabels}
memberIds={projectMemberIds ?? undefined}
states={projectStates}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/>
</FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end">
Expand All @@ -152,6 +154,8 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
handleDisplayFiltersUpdate={handleDisplayFilters}
displayProperties={issueFilters?.displayProperties ?? {}}
handleDisplayPropertiesUpdate={handleDisplayProperties}
cycleViewDisabled={!currentProjectDetails?.cycle_view}
moduleViewDisabled={!currentProjectDetails?.module_view}
/>
</FiltersDropdown>
</div>
Expand Down
4 changes: 4 additions & 0 deletions web/components/headers/project-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
/>
</FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end">
Expand All @@ -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}
/>
</FiltersDropdown>
</div>
Expand Down
4 changes: 4 additions & 0 deletions web/components/headers/project-view-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
/>
</FiltersDropdown>
<FiltersDropdown title="Display" placement="bottom-end">
Expand All @@ -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}
/>
</FiltersDropdown>
{canUserCreateIssue && (
Expand Down
5 changes: 4 additions & 1 deletion web/components/issues/archived-issues-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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}
/>
</FiltersDropdown>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type Props = {
handleDisplayPropertiesUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void;
layoutDisplayFiltersOptions: ILayoutDisplayFiltersOptions | undefined;
ignoreGroupedFilters?: Partial<TIssueGroupByOptions>[];
cycleViewDisabled?: boolean;
moduleViewDisabled?: boolean;
};

export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
Expand All @@ -31,17 +33,32 @@ export const DisplayFiltersSelection: React.FC<Props> = 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<TIssueGroupByOptions>[] = [];
if (cycleViewDisabled) {
ignoreGroupedFilters.push("cycle");
}
if (moduleViewDisabled) {
ignoreGroupedFilters.push("module");
}

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">
{/* display properties */}
{layoutDisplayFiltersOptions?.display_properties && (
<div className="py-2">
<FilterDisplayProperties displayProperties={displayProperties} handleUpdate={handleDisplayPropertiesUpdate} />
<FilterDisplayProperties
displayProperties={displayProperties}
handleUpdate={handleDisplayPropertiesUpdate}
cycleViewDisabled={cycleViewDisabled}
moduleViewDisabled={moduleViewDisabled}
/>
</div>
)}

Expand All @@ -56,7 +73,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
group_by: val,
})
}
ignoreGroupedFilters={ignoreGroupedFilters}
ignoreGroupedFilters={[...ignoreGroupedFilters, ...computedIgnoreGroupedFilters]}
/>
</div>
)}
Expand All @@ -74,7 +91,7 @@ export const DisplayFiltersSelection: React.FC<Props> = observer((props) => {
})
}
subGroupByOptions={layoutDisplayFiltersOptions?.display_filters.sub_group_by ?? []}
ignoreGroupedFilters={ignoreGroupedFilters}
ignoreGroupedFilters={[...ignoreGroupedFilters, ...computedIgnoreGroupedFilters]}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ import { FilterHeader } from "../helpers/filter-header";
type Props = {
displayProperties: IIssueDisplayProperties;
handleUpdate: (updatedDisplayProperties: Partial<IIssueDisplayProperties>) => void;
cycleViewDisabled?: boolean;
moduleViewDisabled?: boolean;
};

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);

// 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 (
<>
<FilterHeader
Expand All @@ -26,23 +35,25 @@ export const FilterDisplayProperties: React.FC<Props> = observer((props) => {
/>
{previewEnabled && (
<div className="mt-1 flex flex-wrap items-center gap-2">
{ISSUE_DISPLAY_PROPERTIES.map((displayProperty) => (
<button
key={displayProperty.key}
type="button"
className={`rounded border px-2 py-0.5 text-xs transition-all ${
displayProperties?.[displayProperty.key]
? "border-custom-primary-100 bg-custom-primary-100 text-white"
: "border-custom-border-200 hover:bg-custom-background-80"
}`}
onClick={() =>
handleUpdate({
[displayProperty.key]: !displayProperties?.[displayProperty.key],
})
}
>
{displayProperty.title}
</button>
{filteredDisplayProperties.map((displayProperty) => (
<>
<button
key={displayProperty.key}
type="button"
className={`rounded border px-2 py-0.5 text-xs transition-all ${
displayProperties?.[displayProperty.key]
? "border-custom-primary-100 bg-custom-primary-100 text-white"
: "border-custom-border-200 hover:bg-custom-background-80"
}`}
onClick={() =>
handleUpdate({
[displayProperty.key]: !displayProperties?.[displayProperty.key],
})
}
>
{displayProperty.title}
</button>
</>
))}
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,21 @@ type Props = {
labels?: IIssueLabel[] | undefined;
memberIds?: string[] | undefined;
states?: IState[] | undefined;
cycleViewDisabled?: boolean;
moduleViewDisabled?: boolean;
};

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
const {
router: { moduleId, cycleId },
Expand Down Expand Up @@ -111,7 +122,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
)}

{/* cycle */}
{isFilterEnabled("cycle") && !cycleId && (
{isFilterEnabled("cycle") && !cycleId && !cycleViewDisabled && (
<div className="py-2">
<FilterCycle
appliedFilters={filters.cycle ?? null}
Expand All @@ -122,7 +133,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
)}

{/* module */}
{isFilterEnabled("module") && !moduleId && (
{isFilterEnabled("module") && !moduleId && !moduleViewDisabled && (
<div className="py-2">
<FilterModule
appliedFilters={filters.module ?? null}
Expand Down

0 comments on commit e9518ce

Please sign in to comment.