Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion packages/constants/src/issue/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { TIssueGroupByOptions, TIssueOrderByOptions, IIssueDisplayProperties } from "@plane/types";
import {
TIssueGroupByOptions,
TIssueOrderByOptions,
IIssueDisplayProperties,
IIssueFilterOptions,
TIssue,
} from "@plane/types";

export const ALL_ISSUES = "All Issues";

Expand Down Expand Up @@ -361,3 +367,17 @@ export const SPREADSHEET_PROPERTY_DETAILS: {
icon: "LayersIcon",
},
};

// Map filter keys to their corresponding issue property keys
export const FILTER_TO_ISSUE_MAP: Partial<Record<keyof IIssueFilterOptions, keyof TIssue>> = {
assignees: "assignee_ids",
created_by: "created_by",
labels: "label_ids",
priority: "priority",
cycle: "cycle_id",
module: "module_ids",
project: "project_id",
state: "state_id",
issue_type: "type_id",
state_group: "state__group",
} as const;
26 changes: 7 additions & 19 deletions packages/constants/src/issue/filter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
ILayoutDisplayFiltersOptions,
TIssueActivityComment,
} from "@plane/types";
import { ILayoutDisplayFiltersOptions, TIssueActivityComment } from "@plane/types";
import {
TIssueFilterPriorityObject,
ISSUE_DISPLAY_PROPERTIES_KEYS,
Expand Down Expand Up @@ -358,9 +355,10 @@ export const ISSUE_DISPLAY_FILTERS_BY_PAGE: TIssueFiltersToDisplayByPageType = {
sub_work_items: {
list: {
display_properties: SUB_ISSUES_DISPLAY_PROPERTIES_KEYS,
filters: [],
filters: ["priority", "state", "project", "issue_type", "assignees", "start_date", "target_date"],
display_filters: {
order_by: ["-created_at", "-updated_at", "start_date", "-priority"],
group_by: ["state", "priority", "assignees", null],
},
extra_options: {
access: true,
Expand All @@ -370,9 +368,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_PAGE: TIssueFiltersToDisplayByPageType = {
},
};

export const ISSUE_STORE_TO_FILTERS_MAP: Partial<
Record<EIssuesStoreType, TFiltersByLayout>
> = {
export const ISSUE_STORE_TO_FILTERS_MAP: Partial<Record<EIssuesStoreType, TFiltersByLayout>> = {
[EIssuesStoreType.PROJECT]: ISSUE_DISPLAY_FILTERS_BY_PAGE.issues,
};

Expand All @@ -383,10 +379,7 @@ export enum EActivityFilterType {

export type TActivityFilters = EActivityFilterType;

export const ACTIVITY_FILTER_TYPE_OPTIONS: Record<
TActivityFilters,
{ labelTranslationKey: string }
> = {
export const ACTIVITY_FILTER_TYPE_OPTIONS: Record<TActivityFilters, { labelTranslationKey: string }> = {
[EActivityFilterType.ACTIVITY]: {
labelTranslationKey: "common.updates",
},
Expand All @@ -402,17 +395,12 @@ export type TActivityFilterOption = {
onClick: () => void;
};

export const defaultActivityFilters: TActivityFilters[] = [
EActivityFilterType.ACTIVITY,
EActivityFilterType.COMMENT,
];
export const defaultActivityFilters: TActivityFilters[] = [EActivityFilterType.ACTIVITY, EActivityFilterType.COMMENT];

export const filterActivityOnSelectedFilters = (
activity: TIssueActivityComment[],
filters: TActivityFilters[]
): TIssueActivityComment[] =>
activity.filter((activity) =>
filters.includes(activity.activity_type as TActivityFilters)
);
activity.filter((activity) => filters.includes(activity.activity_type as TActivityFilters));

export const ENABLE_ISSUE_DEPENDENCIES = false;
1 change: 1 addition & 0 deletions packages/types/src/issues/issue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export type TIssue = TBaseIssue & {
tempId?: string;
// sourceIssueId is used to store the original issue id when creating a copy of an issue. Used in cloning property values. It is not a part of the API response.
sourceIssueId?: string;
state__group?: string | null;
};

export type TIssueMap = {
Expand Down
6 changes: 4 additions & 2 deletions packages/ui/src/collapsible/collapsible-button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC } from "react";
import { cn } from "../../helpers";
import { DropdownIcon } from "../icons";
import { DropdownIcon, ISvgIcons } from "../icons";

type Props = {
isOpen: boolean;
Expand All @@ -10,6 +10,7 @@ type Props = {
actionItemElement?: React.ReactNode;
className?: string;
titleClassName?: string;
ChevronIcon?: React.FC<ISvgIcons>;
};

export const CollapsibleButton: FC<Props> = (props) => {
Expand All @@ -21,6 +22,7 @@ export const CollapsibleButton: FC<Props> = (props) => {
actionItemElement,
className = "",
titleClassName = "",
ChevronIcon = DropdownIcon,
} = props;
return (
<div
Expand All @@ -32,7 +34,7 @@ export const CollapsibleButton: FC<Props> = (props) => {
<div className="flex items-center gap-3.5">
<div className="flex items-center gap-3">
{!hideChevron && (
<DropdownIcon
<ChevronIcon
className={cn("size-2 text-custom-text-300 hover:text-custom-text-200 duration-300", {
"-rotate-90": !isOpen,
})}
Expand Down
11 changes: 9 additions & 2 deletions web/core/components/empty-state/section-empty-state-root.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
"use client";

import { FC } from "react";
import { cn } from "@plane/utils";

type Props = {
icon: React.ReactNode;
title: string;
description?: string;
actionElement?: React.ReactNode;
customClassName?: string;
};

export const SectionEmptyState: FC<Props> = (props) => {
const { title, description, icon, actionElement } = props;
const { title, description, icon, actionElement, customClassName } = props;
return (
<div className="flex flex-col gap-4 items-center justify-center rounded-md border border-custom-border-200 p-10">
<div
className={cn(
"flex flex-col gap-4 items-center justify-center rounded-md border border-custom-border-200 p-10",
customClassName
)}
>
<div className="flex flex-col items-center gap-2">
<div className="flex items-center justify-center size-8 bg-custom-background-80 rounded">{icon}</div>
<span className="text-sm font-medium">{title}</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";
import React, { FC, useEffect, useState, useCallback } from "react";
import { observer } from "mobx-react";
import { EIssueServiceType } from "@plane/constants";
import { EIssueServiceType, EIssuesStoreType } from "@plane/constants";
import { TIssue, TIssueServiceType } from "@plane/types";
// components
import { DeleteIssueModal } from "@/components/issues/delete-issue-modal";
Expand Down Expand Up @@ -117,6 +117,7 @@ export const SubIssuesCollapsibleContent: FC<Props> = observer((props) => {
<>
{subIssueHelpers.issue_visibility.includes(parentIssueId) && (
<SubIssuesListRoot
storeType={EIssuesStoreType.PROJECT}
workspaceSlug={workspaceSlug}
projectId={projectId}
parentIssueId={parentIssueId}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { FC } from "react";
import { FC, useMemo } from "react";
import isEmpty from "lodash/isEmpty";
import { observer } from "mobx-react";
import { SlidersHorizontal } from "lucide-react";
import { IIssueDisplayFilterOptions, ILayoutDisplayFiltersOptions, IIssueDisplayProperties } from "@plane/types";
import { DisplayPropertiesIcon } from "@plane/ui";
import { FilterDisplayProperties, FilterOrderBy, FiltersDropdown } from "@/components/issues";
import { cn } from "@plane/utils";
import { FilterDisplayProperties, FilterGroupBy, FilterOrderBy, FiltersDropdown } from "@/components/issues";
import { isDisplayFiltersApplied } from "@/components/issues/issue-layouts/utils";

type TSubIssueDisplayFiltersProps = {
displayProperties: IIssueDisplayProperties;
Expand All @@ -24,20 +26,29 @@ export const SubIssueDisplayFilters: FC<TSubIssueDisplayFiltersProps> = observer
displayFilters,
} = props;

const isFilterApplied = useMemo(
() => isDisplayFiltersApplied({ displayProperties, displayFilters }),
[displayProperties, displayFilters]
);

return (
<>
{layoutDisplayFiltersOptions?.display_filters && layoutDisplayFiltersOptions?.display_properties.length > 0 && (
<FiltersDropdown
placement="bottom-end"
menuButton={<DisplayPropertiesIcon className="h-3.5 w-3.5 text-custom-text-100" />}
menuButton={
<div
className={cn(
"p-1 rounded relative transition-all duration-200",
isFilterApplied && "bg-custom-primary-60/20"
)}
>
{isFilterApplied && <span className="p-1 rounded-full bg-custom-primary-100 absolute -top-1 -right-1" />}
<SlidersHorizontal className="h-3.5 w-3.5 text-custom-text-100" />
</div>
}
>
<div
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
className="vertical-scrollbar scrollbar-sm relative h-full w-full divide-y divide-custom-border-200 overflow-hidden overflow-y-auto px-2.5 max-h-[25rem] text-left"
>
<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 max-h-[25rem] text-left">
{/* display properties */}
<div className="py-2">
<FilterDisplayProperties
Expand All @@ -48,6 +59,20 @@ export const SubIssueDisplayFilters: FC<TSubIssueDisplayFiltersProps> = observer
/>
</div>

{/* group by */}
<div className="py-2">
<FilterGroupBy
displayFilters={displayFilters}
groupByOptions={layoutDisplayFiltersOptions?.display_filters.group_by ?? []}
handleUpdate={(val) =>
handleDisplayFiltersUpdate({
group_by: val,
})
}
ignoreGroupedFilters={[]}
/>
</div>

{/* order by */}
{!isEmpty(layoutDisplayFiltersOptions?.display_filters?.order_by) && (
<div className="py-2">
Expand Down
Loading