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
1 change: 1 addition & 0 deletions packages/types/src/common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ export type TLogoProps = {
icon?: {
name?: string;
color?: string;
background_color?: string;
};
};
1 change: 1 addition & 0 deletions packages/types/src/issues.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export interface IIssueActivity {
name: string;
priority: string | null;
sequence_id: string;
type_id: string;
} | null;
new_identifier: string | null;
new_value: string | null;
Expand Down
5 changes: 5 additions & 0 deletions packages/types/src/issues/activity/base.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,9 @@ export type TIssueActivityComment =
id: string;
activity_type: "WORKLOG";
created_at?: string;
}
| {
id: string;
activity_type: "ISSUE_ADDITIONAL_PROPERTIES_ACTIVITY";
created_at?: string;
};
1 change: 1 addition & 0 deletions packages/types/src/project/projects.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,5 @@ export interface ISearchIssueResponse {
state__group: TStateGroups;
state__name: string;
workspace__slug: string;
type_id: string;
}
1 change: 1 addition & 0 deletions packages/types/src/workspace.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export interface IWorkspaceIssueSearchResult {
project_id: string;
sequence_id: number;
workspace__slug: string;
type_id: string;
}

export interface IWorkspacePageSearchResult {
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/emoji/emoji-icon-picker-new.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const EmojiIconPicker: React.FC<TCustomEmojiPicker> = (props) => {
type: EmojiIconPickerTypes.EMOJI,
value: val,
});
if (closeOnSelect) close();
if (closeOnSelect) handleToggle(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AnmolBhatia1001 , check this.

}}
height="20rem"
width="100%"
Expand All @@ -120,7 +120,7 @@ export const EmojiIconPicker: React.FC<TCustomEmojiPicker> = (props) => {
type: EmojiIconPickerTypes.ICON,
value: val,
});
if (closeOnSelect) close();
if (closeOnSelect) handleToggle(false);
}}
/>
</Tab.Panel>
Expand Down
11 changes: 4 additions & 7 deletions packages/ui/src/emoji/logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import useFontFaceObserver from "use-font-face-observer";
import { LUCIDE_ICONS_LIST } from "./icons";
// helpers
import { emojiCodeToUnicode } from "./helpers";
import { cn } from "../../helpers";

type TLogoProps = {
in_use: "emoji" | "icon";
Expand All @@ -23,11 +22,10 @@ type Props = {
logo: TLogoProps;
size?: number;
type?: "lucide" | "material";
customColor?: string;
};

export const Logo: FC<Props> = (props) => {
const { logo, size = 16, customColor, type = "material" } = props;
const { logo, size = 16, type = "material" } = props;

// destructuring the logo object
const { in_use, emoji, icon } = logo;
Expand Down Expand Up @@ -74,20 +72,19 @@ export const Logo: FC<Props> = (props) => {
{lucideIcon && (
<lucideIcon.element
style={{
color: !customColor ? color : undefined,
color: color,
height: size,
width: size,
}}
className={cn(customColor)}
/>
)}
</>
) : (
<span
className={cn("material-symbols-rounded", customColor)}
className="material-symbols-rounded"
style={{
fontSize: size,
color: !customColor ? color : undefined,
color: color,
scale: "115%",
}}
>
Expand Down
35 changes: 25 additions & 10 deletions packages/ui/src/sortable/sortable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import React, { Fragment, useEffect, useMemo } from "react";
import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
import { Draggable } from "./draggable";

type TEnhancedData<T> = T & { __uuid__?: string };

type Props<T> = {
data: T[];
data: TEnhancedData<T>[];
render: (item: T, index: number) => React.ReactNode;
onChange: (data: T[], movedItem?: T) => void;
keyExtractor: (item: T, index: number) => string;
Expand All @@ -12,9 +14,9 @@ type Props<T> = {
};

const moveItem = <T,>(
data: T[],
source: T,
destination: T & Record<symbol, string>,
data: TEnhancedData<T>[],
source: TEnhancedData<T>,
destination: TEnhancedData<T> & Record<symbol, string>,
keyExtractor: (item: T, index: number) => string
): {
newData: T[];
Expand Down Expand Up @@ -44,7 +46,16 @@ const moveItem = <T,>(

newData.splice(adjustedDestinationIndex, 0, movedItem);

return { newData, movedItem };
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { __uuid__: movedItemId, ...movedItemData } = movedItem;
return {
newData: newData.map((item) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { __uuid__: uuid, ...rest } = item;
return rest as T;
}),
movedItem: movedItemData as T,
};
};

export const Sortable = <T,>({ data, render, onChange, keyExtractor, containerClassName, id }: Props<T>) => {
Expand All @@ -55,8 +66,8 @@ export const Sortable = <T,>({ data, render, onChange, keyExtractor, containerCl
if (!destination) return;
const { newData, movedItem } = moveItem(
data,
source.data as T,
destination.data as T & { closestEdge: string },
source.data as TEnhancedData<T>,
destination.data as TEnhancedData<T> & { closestEdge: string },
keyExtractor
);
onChange(newData, movedItem);
Expand All @@ -76,9 +87,13 @@ export const Sortable = <T,>({ data, render, onChange, keyExtractor, containerCl

return (
<>
{enhancedData.map((item, index) => (
<Draggable key={keyExtractor(item, index)} data={item} className={containerClassName}>
<Fragment>{render(item, index)} </Fragment>
{data.map((item, index) => (
<Draggable
key={keyExtractor(enhancedData[index], index)}
data={enhancedData[index]}
className={containerClassName}
>
<Fragment>{render(item, index)}</Fragment>
</Draggable>
))}
</>
Expand Down
1 change: 1 addition & 0 deletions web/ce/components/issues/issue-details/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./issue-identifier";
export * from "./issue-properties-activity";
33 changes: 25 additions & 8 deletions web/ce/components/issues/issue-details/issue-identifier.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
import { observer } from "mobx-react";
// helpers
import { cn } from "@/helpers/common.helper";
// hooks
import { useIssueDetail, useProject } from "@/hooks/store";

type TIssueIdentifierProps = {
issueId: string;
type TIssueIdentifierBaseProps = {
projectId: string;
size?: "xs" | "sm" | "md" | "lg";
textContainerClassName?: string;
};

type TIssueIdentifierFromStore = TIssueIdentifierBaseProps & {
issueId: string;
};

type TIssueIdentifierWithDetails = TIssueIdentifierBaseProps & {
issueTypeId?: string | null;
projectIdentifier: string;
issueSequenceId: string | number;
};

type TIssueIdentifierProps = TIssueIdentifierFromStore | TIssueIdentifierWithDetails;
export const IssueIdentifier: React.FC<TIssueIdentifierProps> = observer((props) => {
const { issueId, projectId } = props;
const { projectId, textContainerClassName } = props;
// store hooks
const { getProjectById } = useProject();
const { getProjectIdentifierById } = useProject();
const {
issue: { getIssueById },
} = useIssueDetail();
// Determine if the component is using store data or not
const isUsingStoreData = "issueId" in props;
// derived values
const issue = getIssueById(issueId);
const projectDetails = getProjectById(projectId);
const issue = isUsingStoreData ? getIssueById(props.issueId) : null;
const projectIdentifier = isUsingStoreData ? getProjectIdentifierById(projectId) : props.projectIdentifier;
const issueSequenceId = isUsingStoreData ? issue?.sequence_id : props.issueSequenceId;

return (
<div className="flex items-center space-x-2">
<span className="text-base font-medium text-custom-text-300">
{projectDetails?.identifier}-{issue?.sequence_id}
<span className={cn("text-base font-medium text-custom-text-300", textContainerClassName)}>
{projectIdentifier}-{issueSequenceId}
</span>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./root";
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { FC } from "react";

type TIssueAdditionalPropertiesActivity = {
activityId: string;
ends: "top" | "bottom" | undefined;
};

export const IssueAdditionalPropertiesActivity: FC<TIssueAdditionalPropertiesActivity> = () => <></>;
34 changes: 20 additions & 14 deletions web/core/components/command-palette/command-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import { useParams } from "next/navigation";
import useSWR from "swr";
import { FolderPlus, Search, Settings } from "lucide-react";
import { Dialog, Transition } from "@headlessui/react";
// icons
// types
import { IWorkspaceSearchResults } from "@plane/types";
// hooks
// ui
import { LayersIcon, Loader, ToggleSwitch, Tooltip } from "@plane/ui";
// components
import {
ChangeIssueAssignee,
ChangeIssuePriority,
Expand All @@ -23,28 +24,28 @@ import {
CommandPaletteWorkspaceSettingsActions,
} from "@/components/command-palette";
import { EmptyState } from "@/components/empty-state";
// constants
import { EmptyStateType } from "@/constants/empty-state";
// fetch-keys
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
// hooks
import { useCommandPalette, useEventTracker, useProject, useUser } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
import useDebounce from "@/hooks/use-debounce";
import { usePlatformOS } from "@/hooks/use-platform-os";
// services
// plane web components
import { IssueIdentifier } from "@/plane-web/components/issues";
// plane web services
import { WorkspaceService } from "@/plane-web/services";
// services
import { IssueService } from "@/services/issue";

// ui
// components
// types
// fetch-keys
// constants

const workspaceService = new WorkspaceService();
const issueService = new IssueService();

export const CommandModal: React.FC = observer(() => {
// hooks
const { getProjectById, workspaceProjectIds } = useProject();
const { workspaceProjectIds } = useProject();
const { isMobile } = usePlatformOS();
const { canPerformAnyCreateAction } = useUser();
// states
Expand Down Expand Up @@ -141,8 +142,6 @@ export const CommandModal: React.FC = observer(() => {
[debouncedSearchTerm, isWorkspaceLevel, projectId, workspaceSlug] // Only call effect if debounced search term changes
);

const projectDetails = getProjectById(issueDetails?.project_id ?? "");

return (
<Transition.Root show={isCommandPaletteOpen} afterLeave={() => setSearchTerm("")} as={React.Fragment}>
<Dialog as="div" className="relative z-30" onClose={() => closePalette()}>
Expand Down Expand Up @@ -198,8 +197,15 @@ export const CommandModal: React.FC = observer(() => {
}`}
>
{issueDetails && (
<div className="overflow-hidden truncate rounded-md bg-custom-background-80 p-2 text-xs font-medium text-custom-text-200">
{projectDetails?.identifier}-{issueDetails.sequence_id} {issueDetails.name}
<div className="flex gap-2 items-center overflow-hidden truncate rounded-md bg-custom-background-80 p-2 text-xs font-medium text-custom-text-200">
{issueDetails.project_id && (
<IssueIdentifier
issueId={issueDetails.id}
projectId={issueDetails.project_id}
textContainerClassName="text-xs font-medium text-custom-text-200"
/>
)}
{issueDetails.name}
</div>
)}
{projectId && (
Expand Down
23 changes: 15 additions & 8 deletions web/core/components/command-palette/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import {
IWorkspaceProjectSearchResult,
IWorkspaceSearchResult,
} from "@plane/types";
import { ContrastIcon, DiceIcon, LayersIcon } from "@plane/ui";
// ui
import { ContrastIcon, DiceIcon } from "@plane/ui";
// plane web components
import { IssueIdentifier } from "@/plane-web/components/issues";

export const commandGroups: {
[key: string]: {
icon: JSX.Element;
icon: JSX.Element | null;
itemName: (item: any) => React.ReactNode;
path: (item: any, projectId: string | undefined) => string;
title: string;
Expand All @@ -31,14 +34,18 @@ export const commandGroups: {
title: "Cycles",
},
issue: {
icon: <LayersIcon className="h-3 w-3" />,
icon: null,
itemName: (issue: IWorkspaceIssueSearchResult) => (
<h6>
<span className="text-xs text-custom-text-300">
{issue.project__identifier}-{issue.sequence_id}
</span>{" "}
<div className="flex gap-2">
<IssueIdentifier
projectId={issue.project_id}
issueTypeId={issue.type_id}
projectIdentifier={issue.project__identifier}
issueSequenceId={issue.sequence_id}
textContainerClassName="text-xs"
/>{" "}
{issue.name}
</h6>
</div>
),
path: (issue: IWorkspaceIssueSearchResult) =>
`/${issue?.workspace__slug}/projects/${issue?.project_id}/issues/${issue?.id}`,
Expand Down
Loading