feat: init
This commit is contained in:
23
apps/web/ce/hooks/editor/use-extended-editor-config.ts
Normal file
23
apps/web/ce/hooks/editor/use-extended-editor-config.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useCallback } from "react";
|
||||
// plane imports
|
||||
import type { TExtendedFileHandler } from "@plane/editor";
|
||||
|
||||
export type TExtendedEditorFileHandlersArgs = {
|
||||
projectId?: string;
|
||||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
export type TExtendedEditorConfig = {
|
||||
getExtendedEditorFileHandlers: (args: TExtendedEditorFileHandlersArgs) => TExtendedFileHandler;
|
||||
};
|
||||
|
||||
export const useExtendedEditorConfig = (): TExtendedEditorConfig => {
|
||||
const getExtendedEditorFileHandlers: TExtendedEditorConfig["getExtendedEditorFileHandlers"] = useCallback(
|
||||
() => ({}),
|
||||
[]
|
||||
);
|
||||
|
||||
return {
|
||||
getExtendedEditorFileHandlers,
|
||||
};
|
||||
};
|
||||
2
apps/web/ce/hooks/pages/index.ts
Normal file
2
apps/web/ce/hooks/pages/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./use-pages-pane-extensions";
|
||||
export * from "./use-extended-editor-extensions";
|
||||
20
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts
Normal file
20
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { IEditorPropsExtended } from "@plane/editor";
|
||||
import type { TSearchEntityRequestPayload, TSearchResponse } from "@plane/types";
|
||||
import type { TPageInstance } from "@/store/pages/base-page";
|
||||
import type { EPageStoreType } from "../store";
|
||||
|
||||
export type TExtendedEditorExtensionsHookParams = {
|
||||
workspaceSlug: string;
|
||||
page: TPageInstance;
|
||||
storeType: EPageStoreType;
|
||||
fetchEntity: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
|
||||
getRedirectionLink: (pageId?: string) => string;
|
||||
extensionHandlers?: Map<string, unknown>;
|
||||
projectId?: string;
|
||||
};
|
||||
|
||||
export type TExtendedEditorExtensionsConfig = IEditorPropsExtended;
|
||||
|
||||
export const useExtendedEditorProps = (
|
||||
_params: TExtendedEditorExtensionsHookParams
|
||||
): TExtendedEditorExtensionsConfig => ({});
|
||||
62
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts
Normal file
62
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { useCallback, useMemo } from "react";
|
||||
import type { RefObject } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import type { EditorRefApi } from "@plane/editor";
|
||||
import {
|
||||
PAGE_NAVIGATION_PANE_TAB_KEYS,
|
||||
PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM,
|
||||
PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM,
|
||||
} from "@/components/pages/navigation-pane";
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
import { useQueryParams } from "@/hooks/use-query-params";
|
||||
import type { TPageNavigationPaneTab } from "@/plane-web/components/pages/navigation-pane";
|
||||
import type { INavigationPaneExtension } from "@/plane-web/types/pages/pane-extensions";
|
||||
import type { TPageInstance } from "@/store/pages/base-page";
|
||||
|
||||
export type TPageExtensionHookParams = {
|
||||
page: TPageInstance;
|
||||
editorRef: RefObject<EditorRefApi>;
|
||||
};
|
||||
|
||||
export const usePagesPaneExtensions = (_params: TPageExtensionHookParams) => {
|
||||
const router = useAppRouter();
|
||||
const { updateQueryParams } = useQueryParams();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
// Generic navigation pane logic - hook manages feature-specific routing
|
||||
const navigationPaneQueryParam = searchParams.get(
|
||||
PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM
|
||||
) as TPageNavigationPaneTab | null;
|
||||
|
||||
const isNavigationPaneOpen =
|
||||
!!navigationPaneQueryParam && PAGE_NAVIGATION_PANE_TAB_KEYS.includes(navigationPaneQueryParam);
|
||||
|
||||
const handleOpenNavigationPane = useCallback(() => {
|
||||
const updatedRoute = updateQueryParams({
|
||||
paramsToAdd: { [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM]: "outline" },
|
||||
});
|
||||
router.push(updatedRoute);
|
||||
}, [router, updateQueryParams]);
|
||||
|
||||
const editorExtensionHandlers: Map<string, unknown> = useMemo(() => {
|
||||
const map: Map<string, unknown> = new Map();
|
||||
return map;
|
||||
}, []);
|
||||
|
||||
const navigationPaneExtensions: INavigationPaneExtension[] = [];
|
||||
|
||||
const handleCloseNavigationPane = useCallback(() => {
|
||||
const updatedRoute = updateQueryParams({
|
||||
paramsToRemove: [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM, PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM],
|
||||
});
|
||||
router.push(updatedRoute);
|
||||
}, [router, updateQueryParams]);
|
||||
|
||||
return {
|
||||
editorExtensionHandlers,
|
||||
navigationPaneExtensions,
|
||||
handleOpenNavigationPane,
|
||||
isNavigationPaneOpen,
|
||||
handleCloseNavigationPane,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { TSupportedOperators } from "@plane/types";
|
||||
import { CORE_OPERATORS } from "@plane/types";
|
||||
|
||||
export type TFiltersOperatorConfigs = {
|
||||
allowedOperators: Set<TSupportedOperators>;
|
||||
allowNegative: boolean;
|
||||
};
|
||||
|
||||
export type TUseFiltersOperatorConfigsProps = {
|
||||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
export const useFiltersOperatorConfigs = (_props: TUseFiltersOperatorConfigsProps): TFiltersOperatorConfigs => ({
|
||||
allowedOperators: new Set(Object.values(CORE_OPERATORS)),
|
||||
allowNegative: false,
|
||||
});
|
||||
2
apps/web/ce/hooks/store/index.ts
Normal file
2
apps/web/ce/hooks/store/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./use-page-store";
|
||||
export * from "./use-page";
|
||||
24
apps/web/ce/hooks/store/use-page-store.ts
Normal file
24
apps/web/ce/hooks/store/use-page-store.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { useContext } from "react";
|
||||
// context
|
||||
import { StoreContext } from "@/lib/store-context";
|
||||
// mobx store
|
||||
import type { IProjectPageStore } from "@/store/pages/project-page.store";
|
||||
|
||||
export enum EPageStoreType {
|
||||
PROJECT = "PROJECT_PAGE",
|
||||
}
|
||||
|
||||
export type TReturnType = {
|
||||
[EPageStoreType.PROJECT]: IProjectPageStore;
|
||||
};
|
||||
|
||||
export const usePageStore = <T extends EPageStoreType>(storeType: T): TReturnType[T] => {
|
||||
const context = useContext(StoreContext);
|
||||
if (context === undefined) throw new Error("usePageStore must be used within StoreProvider");
|
||||
|
||||
if (storeType === EPageStoreType.PROJECT) {
|
||||
return context.projectPages;
|
||||
}
|
||||
|
||||
throw new Error(`Invalid store type: ${storeType}`);
|
||||
};
|
||||
24
apps/web/ce/hooks/store/use-page.ts
Normal file
24
apps/web/ce/hooks/store/use-page.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { useContext } from "react";
|
||||
// mobx store
|
||||
import { StoreContext } from "@/lib/store-context";
|
||||
// plane web hooks
|
||||
import type { EPageStoreType } from "@/plane-web/hooks/store";
|
||||
import { usePageStore } from "@/plane-web/hooks/store";
|
||||
|
||||
export type TArgs = {
|
||||
pageId: string;
|
||||
storeType: EPageStoreType;
|
||||
};
|
||||
|
||||
export const usePage = (args: TArgs) => {
|
||||
const { pageId, storeType } = args;
|
||||
// context
|
||||
const context = useContext(StoreContext);
|
||||
// store hooks
|
||||
const pageStore = usePageStore(storeType);
|
||||
|
||||
if (context === undefined) throw new Error("usePage must be used within StoreProvider");
|
||||
if (!pageId) throw new Error("pageId is required");
|
||||
|
||||
return pageStore.getPageById(pageId);
|
||||
};
|
||||
41
apps/web/ce/hooks/use-additional-editor-mention.tsx
Normal file
41
apps/web/ce/hooks/use-additional-editor-mention.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { useCallback } from "react";
|
||||
// plane editor
|
||||
import type { TMentionSection } from "@plane/editor";
|
||||
// plane types
|
||||
import type { TSearchEntities, TSearchResponse } from "@plane/types";
|
||||
|
||||
export type TAdditionalEditorMentionHandlerArgs = {
|
||||
response: TSearchResponse;
|
||||
sections: TMentionSection[];
|
||||
};
|
||||
|
||||
export type TAdditionalParseEditorContentArgs = {
|
||||
id: string;
|
||||
entityType: TSearchEntities;
|
||||
};
|
||||
|
||||
export type TAdditionalParseEditorContentReturnType =
|
||||
| {
|
||||
redirectionPath: string;
|
||||
textContent: string;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
export const useAdditionalEditorMention = () => {
|
||||
const updateAdditionalSections = useCallback((args: TAdditionalEditorMentionHandlerArgs) => {
|
||||
const {} = args;
|
||||
}, []);
|
||||
|
||||
const parseAdditionalEditorContent = useCallback(
|
||||
(args: TAdditionalParseEditorContentArgs): TAdditionalParseEditorContentReturnType => {
|
||||
const {} = args;
|
||||
return undefined;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return {
|
||||
updateAdditionalSections,
|
||||
parseAdditionalEditorContent,
|
||||
};
|
||||
};
|
||||
26
apps/web/ce/hooks/use-additional-favorite-item-details.ts
Normal file
26
apps/web/ce/hooks/use-additional-favorite-item-details.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// plane imports
|
||||
import type { IFavorite } from "@plane/types";
|
||||
// components
|
||||
import { getFavoriteItemIcon } from "@/components/workspace/sidebar/favorites/favorite-items/common";
|
||||
|
||||
export const useAdditionalFavoriteItemDetails = () => {
|
||||
const getAdditionalFavoriteItemDetails = (_workspaceSlug: string, favorite: IFavorite) => {
|
||||
const { entity_type: favoriteItemEntityType } = favorite;
|
||||
const favoriteItemName = favorite?.entity_data?.name || favorite?.name;
|
||||
|
||||
let itemIcon;
|
||||
let itemTitle;
|
||||
|
||||
switch (favoriteItemEntityType) {
|
||||
default:
|
||||
itemTitle = favoriteItemName;
|
||||
itemIcon = getFavoriteItemIcon(favoriteItemEntityType);
|
||||
break;
|
||||
}
|
||||
return { itemIcon, itemTitle };
|
||||
};
|
||||
|
||||
return {
|
||||
getAdditionalFavoriteItemDetails,
|
||||
};
|
||||
};
|
||||
1
apps/web/ce/hooks/use-bulk-operation-status.ts
Normal file
1
apps/web/ce/hooks/use-bulk-operation-status.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const useBulkOperationStatus = () => false;
|
||||
12
apps/web/ce/hooks/use-debounced-duplicate-issues.tsx
Normal file
12
apps/web/ce/hooks/use-debounced-duplicate-issues.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { TDeDupeIssue } from "@plane/types";
|
||||
|
||||
export const useDebouncedDuplicateIssues = (
|
||||
workspaceSlug: string | undefined,
|
||||
workspaceId: string | undefined,
|
||||
projectId: string | undefined,
|
||||
formData: { name: string | undefined; description_html?: string | undefined; issueId?: string | undefined }
|
||||
) => {
|
||||
const duplicateIssues: TDeDupeIssue[] = [];
|
||||
|
||||
return { duplicateIssues };
|
||||
};
|
||||
41
apps/web/ce/hooks/use-editor-flagging.ts
Normal file
41
apps/web/ce/hooks/use-editor-flagging.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
// editor
|
||||
import type { TExtensions } from "@plane/editor";
|
||||
import type { EPageStoreType } from "@/plane-web/hooks/store";
|
||||
|
||||
export type TEditorFlaggingHookReturnType = {
|
||||
document: {
|
||||
disabled: TExtensions[];
|
||||
flagged: TExtensions[];
|
||||
};
|
||||
liteText: {
|
||||
disabled: TExtensions[];
|
||||
flagged: TExtensions[];
|
||||
};
|
||||
richText: {
|
||||
disabled: TExtensions[];
|
||||
flagged: TExtensions[];
|
||||
};
|
||||
};
|
||||
|
||||
export type TEditorFlaggingHookProps = {
|
||||
workspaceSlug: string;
|
||||
storeType?: EPageStoreType;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description extensions disabled in various editors
|
||||
*/
|
||||
export const useEditorFlagging = (_props: TEditorFlaggingHookProps): TEditorFlaggingHookReturnType => ({
|
||||
document: {
|
||||
disabled: ["ai", "collaboration-cursor"],
|
||||
flagged: [],
|
||||
},
|
||||
liteText: {
|
||||
disabled: ["ai", "collaboration-cursor"],
|
||||
flagged: [],
|
||||
},
|
||||
richText: {
|
||||
disabled: ["ai", "collaboration-cursor"],
|
||||
flagged: [],
|
||||
},
|
||||
});
|
||||
17
apps/web/ce/hooks/use-file-size.ts
Normal file
17
apps/web/ce/hooks/use-file-size.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// plane imports
|
||||
import { MAX_FILE_SIZE } from "@plane/constants";
|
||||
// hooks
|
||||
import { useInstance } from "@/hooks/store/use-instance";
|
||||
|
||||
type TReturnProps = {
|
||||
maxFileSize: number;
|
||||
};
|
||||
|
||||
export const useFileSize = (): TReturnProps => {
|
||||
// store hooks
|
||||
const { config } = useInstance();
|
||||
|
||||
return {
|
||||
maxFileSize: config?.file_size_limit ?? MAX_FILE_SIZE,
|
||||
};
|
||||
};
|
||||
25
apps/web/ce/hooks/use-issue-embed.tsx
Normal file
25
apps/web/ce/hooks/use-issue-embed.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
// editor
|
||||
import type { TEmbedConfig } from "@plane/editor";
|
||||
// plane types
|
||||
import type { TSearchEntityRequestPayload, TSearchResponse } from "@plane/types";
|
||||
// plane web components
|
||||
import { IssueEmbedUpgradeCard } from "@/plane-web/components/pages";
|
||||
|
||||
export type TIssueEmbedHookProps = {
|
||||
fetchEmbedSuggestions?: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
|
||||
projectId?: string;
|
||||
workspaceSlug?: string;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const useIssueEmbed = (props: TIssueEmbedHookProps) => {
|
||||
const widgetCallback = () => <IssueEmbedUpgradeCard />;
|
||||
|
||||
const issueEmbedProps: TEmbedConfig["issue"] = {
|
||||
widgetCallback,
|
||||
};
|
||||
|
||||
return {
|
||||
issueEmbedProps,
|
||||
};
|
||||
};
|
||||
10
apps/web/ce/hooks/use-issue-properties.tsx
Normal file
10
apps/web/ce/hooks/use-issue-properties.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { TIssueServiceType } from "@plane/types";
|
||||
|
||||
export const useWorkItemProperties = (
|
||||
projectId: string | null | undefined,
|
||||
workspaceSlug: string | null | undefined,
|
||||
workItemId: string | null | undefined,
|
||||
issueServiceType: TIssueServiceType
|
||||
) => {
|
||||
if (!projectId || !workspaceSlug || !workItemId) return;
|
||||
};
|
||||
25
apps/web/ce/hooks/use-notification-preview.tsx
Normal file
25
apps/web/ce/hooks/use-notification-preview.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { IWorkItemPeekOverview } from "@plane/types";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
import { IssuePeekOverview } from "@/components/issues/peek-overview";
|
||||
import { useIssueDetail } from "@/hooks/store/use-issue-detail";
|
||||
import type { TPeekIssue } from "@/store/issue/issue-details/root.store";
|
||||
|
||||
export type TNotificationPreview = {
|
||||
isWorkItem: boolean;
|
||||
PeekOverviewComponent: React.ComponentType<IWorkItemPeekOverview>;
|
||||
setPeekWorkItem: (peekIssue: TPeekIssue | undefined) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function returns if the current active notification is related to work item or an epic.
|
||||
* @returns isWorkItem: boolean, peekOverviewComponent: IWorkItemPeekOverview, setPeekWorkItem
|
||||
*/
|
||||
export const useNotificationPreview = (): TNotificationPreview => {
|
||||
const { peekIssue, setPeekIssue } = useIssueDetail(EIssueServiceType.ISSUES);
|
||||
|
||||
return {
|
||||
isWorkItem: Boolean(peekIssue),
|
||||
PeekOverviewComponent: IssuePeekOverview,
|
||||
setPeekWorkItem: setPeekIssue,
|
||||
};
|
||||
};
|
||||
16
apps/web/ce/hooks/use-page-flag.ts
Normal file
16
apps/web/ce/hooks/use-page-flag.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export type TPageFlagHookArgs = {
|
||||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
export type TPageFlagHookReturnType = {
|
||||
isMovePageEnabled: boolean;
|
||||
isPageSharingEnabled: boolean;
|
||||
};
|
||||
|
||||
export const usePageFlag = (args: TPageFlagHookArgs): TPageFlagHookReturnType => {
|
||||
const {} = args;
|
||||
return {
|
||||
isMovePageEnabled: false,
|
||||
isPageSharingEnabled: false,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const useWorkspaceIssuePropertiesExtended = (workspaceSlug: string | string[] | undefined) => {};
|
||||
@@ -0,0 +1,401 @@
|
||||
import { useCallback, useMemo } from "react";
|
||||
import {
|
||||
AtSign,
|
||||
Briefcase,
|
||||
Calendar,
|
||||
CalendarCheck2,
|
||||
CalendarClock,
|
||||
CircleUserRound,
|
||||
SignalHigh,
|
||||
Tag,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
// plane imports
|
||||
import {
|
||||
CycleGroupIcon,
|
||||
CycleIcon,
|
||||
ModuleIcon,
|
||||
DoubleCircleIcon,
|
||||
PriorityIcon,
|
||||
StateGroupIcon,
|
||||
} from "@plane/propel/icons";
|
||||
import type {
|
||||
ICycle,
|
||||
IState,
|
||||
IUserLite,
|
||||
TFilterConfig,
|
||||
TFilterValue,
|
||||
IIssueLabel,
|
||||
IModule,
|
||||
IProject,
|
||||
TWorkItemFilterProperty,
|
||||
} from "@plane/types";
|
||||
import { Avatar, Logo } from "@plane/ui";
|
||||
import {
|
||||
getAssigneeFilterConfig,
|
||||
getCreatedAtFilterConfig,
|
||||
getCreatedByFilterConfig,
|
||||
getCycleFilterConfig,
|
||||
getFileURL,
|
||||
getLabelFilterConfig,
|
||||
getMentionFilterConfig,
|
||||
getModuleFilterConfig,
|
||||
getPriorityFilterConfig,
|
||||
getProjectFilterConfig,
|
||||
getStartDateFilterConfig,
|
||||
getStateFilterConfig,
|
||||
getStateGroupFilterConfig,
|
||||
getSubscriberFilterConfig,
|
||||
getTargetDateFilterConfig,
|
||||
getUpdatedAtFilterConfig,
|
||||
isLoaderReady,
|
||||
} from "@plane/utils";
|
||||
// store hooks
|
||||
import { useCycle } from "@/hooks/store/use-cycle";
|
||||
import { useLabel } from "@/hooks/store/use-label";
|
||||
import { useMember } from "@/hooks/store/use-member";
|
||||
import { useModule } from "@/hooks/store/use-module";
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { useProjectState } from "@/hooks/store/use-project-state";
|
||||
// plane web imports
|
||||
import { useFiltersOperatorConfigs } from "@/plane-web/hooks/rich-filters/use-filters-operator-configs";
|
||||
|
||||
export type TWorkItemFiltersEntityProps = {
|
||||
workspaceSlug: string;
|
||||
cycleIds?: string[];
|
||||
labelIds?: string[];
|
||||
memberIds?: string[];
|
||||
moduleIds?: string[];
|
||||
projectId?: string;
|
||||
projectIds?: string[];
|
||||
stateIds?: string[];
|
||||
};
|
||||
|
||||
export type TUseWorkItemFiltersConfigProps = {
|
||||
allowedFilters: TWorkItemFilterProperty[];
|
||||
} & TWorkItemFiltersEntityProps;
|
||||
|
||||
export type TWorkItemFiltersConfig = {
|
||||
areAllConfigsInitialized: boolean;
|
||||
configs: TFilterConfig<TWorkItemFilterProperty, TFilterValue>[];
|
||||
configMap: {
|
||||
[key in TWorkItemFilterProperty]?: TFilterConfig<TWorkItemFilterProperty, TFilterValue>;
|
||||
};
|
||||
isFilterEnabled: (key: TWorkItemFilterProperty) => boolean;
|
||||
members: IUserLite[];
|
||||
};
|
||||
|
||||
export const useWorkItemFiltersConfig = (props: TUseWorkItemFiltersConfigProps): TWorkItemFiltersConfig => {
|
||||
const { allowedFilters, cycleIds, labelIds, memberIds, moduleIds, projectId, projectIds, stateIds, workspaceSlug } =
|
||||
props;
|
||||
// store hooks
|
||||
const { loader: projectLoader, getProjectById } = useProject();
|
||||
const { getCycleById } = useCycle();
|
||||
const { getLabelById } = useLabel();
|
||||
const { getModuleById } = useModule();
|
||||
const { getStateById } = useProjectState();
|
||||
const { getUserDetails } = useMember();
|
||||
// derived values
|
||||
const operatorConfigs = useFiltersOperatorConfigs({ workspaceSlug });
|
||||
const filtersToShow = useMemo(() => new Set(allowedFilters), [allowedFilters]);
|
||||
const project = useMemo(() => getProjectById(projectId), [projectId, getProjectById]);
|
||||
const members: IUserLite[] | undefined = useMemo(
|
||||
() =>
|
||||
memberIds
|
||||
? (memberIds.map((memberId) => getUserDetails(memberId)).filter((member) => member) as IUserLite[])
|
||||
: undefined,
|
||||
[memberIds, getUserDetails]
|
||||
);
|
||||
const workItemStates: IState[] | undefined = useMemo(
|
||||
() =>
|
||||
stateIds ? (stateIds.map((stateId) => getStateById(stateId)).filter((state) => state) as IState[]) : undefined,
|
||||
[stateIds, getStateById]
|
||||
);
|
||||
const workItemLabels: IIssueLabel[] | undefined = useMemo(
|
||||
() =>
|
||||
labelIds
|
||||
? (labelIds.map((labelId) => getLabelById(labelId)).filter((label) => label) as IIssueLabel[])
|
||||
: undefined,
|
||||
[labelIds, getLabelById]
|
||||
);
|
||||
const cycles = useMemo(
|
||||
() => (cycleIds ? (cycleIds.map((cycleId) => getCycleById(cycleId)).filter((cycle) => cycle) as ICycle[]) : []),
|
||||
[cycleIds, getCycleById]
|
||||
);
|
||||
const modules = useMemo(
|
||||
() =>
|
||||
moduleIds ? (moduleIds.map((moduleId) => getModuleById(moduleId)).filter((module) => module) as IModule[]) : [],
|
||||
[moduleIds, getModuleById]
|
||||
);
|
||||
const projects = useMemo(
|
||||
() =>
|
||||
projectIds
|
||||
? (projectIds.map((projectId) => getProjectById(projectId)).filter((project) => project) as IProject[])
|
||||
: [],
|
||||
[projectIds, getProjectById]
|
||||
);
|
||||
const areAllConfigsInitialized = useMemo(() => isLoaderReady(projectLoader), [projectLoader]);
|
||||
|
||||
/**
|
||||
* Checks if a filter is enabled based on the filters to show.
|
||||
* @param key - The filter key.
|
||||
* @param level - The level of the filter.
|
||||
* @returns True if the filter is enabled, false otherwise.
|
||||
*/
|
||||
const isFilterEnabled = useCallback((key: TWorkItemFilterProperty) => filtersToShow.has(key), [filtersToShow]);
|
||||
|
||||
// state group filter config
|
||||
const stateGroupFilterConfig = useMemo(
|
||||
() =>
|
||||
getStateGroupFilterConfig<TWorkItemFilterProperty>("state_group")({
|
||||
isEnabled: isFilterEnabled("state_group"),
|
||||
filterIcon: DoubleCircleIcon,
|
||||
getOptionIcon: (stateGroupKey) => <StateGroupIcon stateGroup={stateGroupKey} />,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, operatorConfigs]
|
||||
);
|
||||
|
||||
// state filter config
|
||||
const stateFilterConfig = useMemo(
|
||||
() =>
|
||||
getStateFilterConfig<TWorkItemFilterProperty>("state_id")({
|
||||
isEnabled: isFilterEnabled("state_id") && workItemStates !== undefined,
|
||||
filterIcon: DoubleCircleIcon,
|
||||
getOptionIcon: (state) => <StateGroupIcon stateGroup={state.group} color={state.color} />,
|
||||
states: workItemStates ?? [],
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, workItemStates, operatorConfigs]
|
||||
);
|
||||
|
||||
// label filter config
|
||||
const labelFilterConfig = useMemo(
|
||||
() =>
|
||||
getLabelFilterConfig<TWorkItemFilterProperty>("label_id")({
|
||||
isEnabled: isFilterEnabled("label_id") && workItemLabels !== undefined,
|
||||
filterIcon: Tag,
|
||||
labels: workItemLabels ?? [],
|
||||
getOptionIcon: (color) => (
|
||||
<span className="flex flex-shrink-0 size-2.5 rounded-full" style={{ backgroundColor: color }} />
|
||||
),
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, workItemLabels, operatorConfigs]
|
||||
);
|
||||
|
||||
// cycle filter config
|
||||
const cycleFilterConfig = useMemo(
|
||||
() =>
|
||||
getCycleFilterConfig<TWorkItemFilterProperty>("cycle_id")({
|
||||
isEnabled: isFilterEnabled("cycle_id") && project?.cycle_view === true && cycles !== undefined,
|
||||
filterIcon: CycleIcon,
|
||||
getOptionIcon: (cycleGroup) => <CycleGroupIcon cycleGroup={cycleGroup} className="h-3.5 w-3.5 flex-shrink-0" />,
|
||||
cycles: cycles ?? [],
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, project?.cycle_view, cycles, operatorConfigs]
|
||||
);
|
||||
|
||||
// module filter config
|
||||
const moduleFilterConfig = useMemo(
|
||||
() =>
|
||||
getModuleFilterConfig<TWorkItemFilterProperty>("module_id")({
|
||||
isEnabled: isFilterEnabled("module_id") && project?.module_view === true && modules !== undefined,
|
||||
filterIcon: ModuleIcon,
|
||||
getOptionIcon: () => <ModuleIcon className="h-3 w-3 flex-shrink-0" />,
|
||||
modules: modules ?? [],
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, project?.module_view, modules, operatorConfigs]
|
||||
);
|
||||
|
||||
// assignee filter config
|
||||
const assigneeFilterConfig = useMemo(
|
||||
() =>
|
||||
getAssigneeFilterConfig<TWorkItemFilterProperty>("assignee_id")({
|
||||
isEnabled: isFilterEnabled("assignee_id") && members !== undefined,
|
||||
filterIcon: Users,
|
||||
members: members ?? [],
|
||||
getOptionIcon: (memberDetails) => (
|
||||
<Avatar
|
||||
name={memberDetails.display_name}
|
||||
src={getFileURL(memberDetails.avatar_url)}
|
||||
showTooltip={false}
|
||||
size="sm"
|
||||
/>
|
||||
),
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, members, operatorConfigs]
|
||||
);
|
||||
|
||||
// mention filter config
|
||||
const mentionFilterConfig = useMemo(
|
||||
() =>
|
||||
getMentionFilterConfig<TWorkItemFilterProperty>("mention_id")({
|
||||
isEnabled: isFilterEnabled("mention_id") && members !== undefined,
|
||||
filterIcon: AtSign,
|
||||
members: members ?? [],
|
||||
getOptionIcon: (memberDetails) => (
|
||||
<Avatar
|
||||
name={memberDetails.display_name}
|
||||
src={getFileURL(memberDetails.avatar_url)}
|
||||
showTooltip={false}
|
||||
size="sm"
|
||||
/>
|
||||
),
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, members, operatorConfigs]
|
||||
);
|
||||
|
||||
// created by filter config
|
||||
const createdByFilterConfig = useMemo(
|
||||
() =>
|
||||
getCreatedByFilterConfig<TWorkItemFilterProperty>("created_by_id")({
|
||||
isEnabled: isFilterEnabled("created_by_id") && members !== undefined,
|
||||
filterIcon: CircleUserRound,
|
||||
members: members ?? [],
|
||||
getOptionIcon: (memberDetails) => (
|
||||
<Avatar
|
||||
name={memberDetails.display_name}
|
||||
src={getFileURL(memberDetails.avatar_url)}
|
||||
showTooltip={false}
|
||||
size="sm"
|
||||
/>
|
||||
),
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, members, operatorConfigs]
|
||||
);
|
||||
|
||||
// subscriber filter config
|
||||
const subscriberFilterConfig = useMemo(
|
||||
() =>
|
||||
getSubscriberFilterConfig<TWorkItemFilterProperty>("subscriber_id")({
|
||||
isEnabled: isFilterEnabled("subscriber_id") && members !== undefined,
|
||||
filterIcon: Users,
|
||||
members: members ?? [],
|
||||
getOptionIcon: (memberDetails) => (
|
||||
<Avatar
|
||||
name={memberDetails.display_name}
|
||||
src={getFileURL(memberDetails.avatar_url)}
|
||||
showTooltip={false}
|
||||
size="sm"
|
||||
/>
|
||||
),
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, members, operatorConfigs]
|
||||
);
|
||||
|
||||
// priority filter config
|
||||
const priorityFilterConfig = useMemo(
|
||||
() =>
|
||||
getPriorityFilterConfig<TWorkItemFilterProperty>("priority")({
|
||||
isEnabled: isFilterEnabled("priority"),
|
||||
filterIcon: SignalHigh,
|
||||
getOptionIcon: (priority) => <PriorityIcon priority={priority} />,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, operatorConfigs]
|
||||
);
|
||||
|
||||
// start date filter config
|
||||
const startDateFilterConfig = useMemo(
|
||||
() =>
|
||||
getStartDateFilterConfig<TWorkItemFilterProperty>("start_date")({
|
||||
isEnabled: true,
|
||||
filterIcon: CalendarClock,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[operatorConfigs]
|
||||
);
|
||||
|
||||
// target date filter config
|
||||
const targetDateFilterConfig = useMemo(
|
||||
() =>
|
||||
getTargetDateFilterConfig<TWorkItemFilterProperty>("target_date")({
|
||||
isEnabled: true,
|
||||
filterIcon: CalendarCheck2,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[operatorConfigs]
|
||||
);
|
||||
|
||||
// created at filter config
|
||||
const createdAtFilterConfig = useMemo(
|
||||
() =>
|
||||
getCreatedAtFilterConfig<TWorkItemFilterProperty>("created_at")({
|
||||
isEnabled: true,
|
||||
filterIcon: Calendar,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[operatorConfigs]
|
||||
);
|
||||
|
||||
// updated at filter config
|
||||
const updatedAtFilterConfig = useMemo(
|
||||
() =>
|
||||
getUpdatedAtFilterConfig<TWorkItemFilterProperty>("updated_at")({
|
||||
isEnabled: true,
|
||||
filterIcon: Calendar,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[operatorConfigs]
|
||||
);
|
||||
|
||||
// project filter config
|
||||
const projectFilterConfig = useMemo(
|
||||
() =>
|
||||
getProjectFilterConfig<TWorkItemFilterProperty>("project_id")({
|
||||
isEnabled: isFilterEnabled("project_id") && projects !== undefined,
|
||||
filterIcon: Briefcase,
|
||||
projects: projects,
|
||||
getOptionIcon: (project) => <Logo logo={project.logo_props} size={12} />,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[isFilterEnabled, projects, operatorConfigs]
|
||||
);
|
||||
|
||||
return {
|
||||
areAllConfigsInitialized,
|
||||
configs: [
|
||||
stateFilterConfig,
|
||||
stateGroupFilterConfig,
|
||||
assigneeFilterConfig,
|
||||
priorityFilterConfig,
|
||||
projectFilterConfig,
|
||||
mentionFilterConfig,
|
||||
labelFilterConfig,
|
||||
cycleFilterConfig,
|
||||
moduleFilterConfig,
|
||||
startDateFilterConfig,
|
||||
targetDateFilterConfig,
|
||||
createdAtFilterConfig,
|
||||
updatedAtFilterConfig,
|
||||
createdByFilterConfig,
|
||||
subscriberFilterConfig,
|
||||
],
|
||||
configMap: {
|
||||
project_id: projectFilterConfig,
|
||||
state_group: stateGroupFilterConfig,
|
||||
state_id: stateFilterConfig,
|
||||
label_id: labelFilterConfig,
|
||||
cycle_id: cycleFilterConfig,
|
||||
module_id: moduleFilterConfig,
|
||||
assignee_id: assigneeFilterConfig,
|
||||
mention_id: mentionFilterConfig,
|
||||
created_by_id: createdByFilterConfig,
|
||||
subscriber_id: subscriberFilterConfig,
|
||||
priority: priorityFilterConfig,
|
||||
start_date: startDateFilterConfig,
|
||||
target_date: targetDateFilterConfig,
|
||||
created_at: createdAtFilterConfig,
|
||||
updated_at: updatedAtFilterConfig,
|
||||
},
|
||||
isFilterEnabled,
|
||||
members: members ?? [],
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user