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
32 changes: 19 additions & 13 deletions packages/ui/src/tooltip/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type TPosition =
interface ITooltipProps {
tooltipHeading?: string;
tooltipContent: string | React.ReactNode;
jsxContent?: string | React.ReactNode;
position?: TPosition;
children: JSX.Element;
disabled?: boolean;
Expand All @@ -38,13 +39,14 @@ export const Tooltip: React.FC<ITooltipProps> = ({
tooltipContent,
position = "top",
children,
jsxContent,
disabled = false,
className = "",
openDelay = 200,
closeDelay,
isMobile = false,
renderByDefault = true, //FIXME: tooltip should always render on hover and not by default, this is a temporary fix
}) => {
}: ITooltipProps) => {
const toolTipRef = useRef<HTMLDivElement | null>(null);

const [shouldRender, setShouldRender] = useState(renderByDefault);
Expand Down Expand Up @@ -79,18 +81,22 @@ export const Tooltip: React.FC<ITooltipProps> = ({
hoverOpenDelay={openDelay}
hoverCloseDelay={closeDelay}
content={
<div
className={cn(
"relative block z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-custom-background-100 p-2 text-xs text-custom-text-200 shadow-md",
{
hidden: isMobile,
},
className
)}
>
{tooltipHeading && <h5 className="font-medium text-custom-text-100">{tooltipHeading}</h5>}
{tooltipContent}
</div>
jsxContent ? (
<>{jsxContent}</>
) : (
<div
className={cn(
"relative block z-50 max-w-xs gap-1 overflow-hidden break-words rounded-md bg-custom-background-100 p-2 text-xs text-custom-text-200 shadow-md",
{
hidden: isMobile,
},
className
)}
>
{tooltipHeading && <h5 className="font-medium text-custom-text-100">{tooltipHeading}</h5>}
{tooltipContent}
</div>
)
}
position={position}
renderTarget={({
Expand Down
20 changes: 20 additions & 0 deletions web/ce/components/workflow/add-state-transition.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Plus } from "lucide-react";
// Plane
import { cn } from "@plane/editor";

type Props = {
workspaceSlug: string;
projectId: string;
parentStateId: string;
onTransitionAdd?: () => void;
};

export const AddStateTransition = (props: Props) => (
<div className={cn("flex w-full px-3 h-6 items-center justify-start gap-2 text-sm bg-custom-background-90")}>
<>
<Plus className="h-4 w-4" color="#8591AD" />
<span className="text-custom-text-400 font-medium"> Add Transition</span>
<div className="text-white bg-custom-background-80 font-semibold px-2 rounded-lg">Pro</div>
</>
</div>
);
Comment on lines +12 to +20
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

AddStateTransition component lacks interaction handling

The onTransitionAdd prop is defined but not utilized. Consider adding an onClick handler to invoke onTransitionAdd when the component is clicked.

Apply this diff to add the onClick handler:

export const AddStateTransition = (props: Props) => (
  <div
    className={cn("flex w-full px-3 h-6 items-center justify-start gap-2 text-sm bg-custom-background-90")}
+   onClick={props.onTransitionAdd}
  >
    <Plus className="h-4 w-4" color="#8591AD" />
    <span className="text-custom-text-400 font-medium"> Add Transition</span>
    <div className="text-white bg-custom-background-80 font-semibold px-2 rounded-lg">Pro</div>
  </div>
);

Committable suggestion skipped: line range outside the PR's diff.

6 changes: 6 additions & 0 deletions web/ce/components/workflow/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from "./state-option";
export * from "./state-item-child";
export * from "./state-transition-count";
export * from "./use-workflow-drag-n-drop";
export * from "./workflow-disabled-message";
export * from "./workflow-group-tree";
35 changes: 35 additions & 0 deletions web/ce/components/workflow/state-item-child.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { SetStateAction } from "react";
import { observer } from "mobx-react";
// Plane
import { IState } from "@plane/types";
// components
import { StateItemTitle } from "@/components/project-states/state-item-title";
//
import { AddStateTransition } from "./add-state-transition";

export type StateItemChildProps = {
workspaceSlug: string;
projectId: string;
stateCount: number;
disabled: boolean;
state: IState;
setUpdateStateModal: (value: SetStateAction<boolean>) => void;
};

export const StateItemChild = observer((props: StateItemChildProps) => {
const { workspaceSlug, projectId, stateCount, setUpdateStateModal, disabled, state } = props;

return (
<div className="flex flex-col w-full items-center justify-between">
<StateItemTitle
workspaceSlug={workspaceSlug}
projectId={projectId}
setUpdateStateModal={setUpdateStateModal}
stateCount={stateCount}
disabled={disabled}
state={state}
/>
<AddStateTransition workspaceSlug={workspaceSlug} projectId={projectId} parentStateId={state.id} />
</div>
);
});
36 changes: 36 additions & 0 deletions web/ce/components/workflow/state-option.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { observer } from "mobx-react";
import { Check } from "lucide-react";
import { Combobox } from "@headlessui/react";

type Props = {
projectId: string | null | undefined;
option: {
value: string | undefined;
query: string;
content: JSX.Element;
};
filterAvailableStateIds: boolean;
selectedValue: string | null | undefined;
className?: string;
};
Comment on lines +5 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider strengthening prop types and removing unused props

The Props type definition has some potential improvements:

  • projectId and selectedValue being nullable/undefined might lead to runtime issues
  • filterAvailableStateIds is defined but not used in the component

Consider this improvement:

 type Props = {
-  projectId: string | null | undefined;
+  projectId: string;
   option: {
-    value: string | undefined;
+    value: string;
     query: string;
     content: JSX.Element;
   };
-  filterAvailableStateIds: boolean;
-  selectedValue: string | null | undefined;
+  selectedValue: string;
   className?: string;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type Props = {
projectId: string | null | undefined;
option: {
value: string | undefined;
query: string;
content: JSX.Element;
};
filterAvailableStateIds: boolean;
selectedValue: string | null | undefined;
className?: string;
};
type Props = {
projectId: string;
option: {
value: string;
query: string;
content: JSX.Element;
};
selectedValue: string;
className?: string;
};


export const StateOption = observer((props: Props) => {
const { option, className = "" } = props;

return (
<Combobox.Option
key={option.value}
value={option.value}
className={({ active, selected }) =>
`${className} ${active ? "bg-custom-background-80" : ""} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
>
{({ selected }) => (
<>
<span className="flex-grow truncate">{option.content}</span>
{selected && <Check className="h-3.5 w-3.5 flex-shrink-0" />}
</>
)}
</Combobox.Option>
);
});
7 changes: 7 additions & 0 deletions web/ce/components/workflow/state-transition-count.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IStateWorkFlow } from "@/plane-web/types";

type Props = {
currentTransitionMap?: IStateWorkFlow;
};

export const StateTransitionCount = (props: Props) => <></>;
15 changes: 15 additions & 0 deletions web/ce/components/workflow/use-workflow-drag-n-drop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { TIssueGroupByOptions } from "@plane/types";

export const useWorkFlowFDragNDrop = (
groupBy: TIssueGroupByOptions | undefined,
subGroupBy?: TIssueGroupByOptions
) => ({
workflowDisabledSource: undefined,
isWorkflowDropDisabled: false,
handleWorkFlowState: (
sourceGroupId: string,
destinationGroupId: string,
sourceSubGroupId?: string,
destinationSubGroupId?: string
) => {},
});
Comment on lines +1 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Empty implementation in useWorkFlowFDragNDrop hook

The useWorkFlowFDragNDrop hook currently returns default values, and the handleWorkFlowState function lacks implementation. Ensure that the necessary logic is implemented to manage workflow drag-and-drop states effectively.

6 changes: 6 additions & 0 deletions web/ce/components/workflow/workflow-disabled-message.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type Props = {
parentStateId: string;
className?: string;
};

export const WorkFlowDisabledMessage = (props: Props) => <></>;
8 changes: 8 additions & 0 deletions web/ce/components/workflow/workflow-group-tree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { TIssueGroupByOptions } from "@plane/types";

type Props = {
groupBy?: TIssueGroupByOptions;
groupId: string | undefined;
};

export const WorkFlowGroupTree = (props: Props) => <></>;
2 changes: 1 addition & 1 deletion web/ce/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "./project";
export * from "./workspace.service";
export * from "./workspace.service";
1 change: 1 addition & 0 deletions web/ce/services/project/project-state.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "@/services/project/project-state.service";
1 change: 1 addition & 0 deletions web/ce/store/state.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "@/store/state.store";
1 change: 1 addition & 0 deletions web/ce/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./projects";
export * from "./issue-types";
export * from "./gantt-chart";
export * from "./state.d";
8 changes: 8 additions & 0 deletions web/ce/types/state.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface IStateTransition {
transition_state_id: string;
actors: string[];
}

export interface IStateWorkFlow {
[transitionId: string]: IStateTransition;
}
42 changes: 21 additions & 21 deletions web/core/components/dropdowns/state.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"use client";

import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { usePopper } from "react-popper";
import { Check, ChevronDown, Search } from "lucide-react";
import { ChevronDown, Search } from "lucide-react";
import { Combobox } from "@headlessui/react";
// ui
import { ComboDropDown, Spinner, StateGroupIcon } from "@plane/ui";
Expand All @@ -13,6 +13,8 @@ import { cn } from "@/helpers/common.helper";
// hooks
import { useProjectState } from "@/hooks/store";
import { useDropdown } from "@/hooks/use-dropdown";
// Plane-web
import { StateOption } from "@/plane-web/components/workflow";
// components
import { DropdownButton } from "./buttons";
// constants
Expand All @@ -30,6 +32,8 @@ type Props = TDropdownProps & {
showDefaultState?: boolean;
value: string | undefined | null;
renderByDefault?: boolean;
stateIds?: string[];
filterAvailableStateIds?: boolean;
};

export const StateDropdown: React.FC<Props> = observer((props) => {
Expand All @@ -52,6 +56,8 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
tabIndex,
value,
renderByDefault = true,
stateIds,
filterAvailableStateIds = true,
} = props;
// states
const [query, setQuery] = useState("");
Expand All @@ -78,16 +84,18 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
// store hooks
const { workspaceSlug } = useParams();
const { fetchProjectStates, getProjectStates, getStateById } = useProjectState();
const statesList = getProjectStates(projectId);
const defaultState = statesList?.find((state) => state.default);
const statesList = stateIds
? stateIds.map((stateId) => getStateById(stateId)).filter((state) => !!state)
: getProjectStates(projectId);
const defaultState = statesList?.find((state) => state?.default);
const stateValue = !!value ? value : showDefaultState ? defaultState?.id : undefined;

const options = statesList?.map((state) => ({
value: state.id,
value: state?.id,
query: `${state?.name}`,
content: (
<div className="flex items-center gap-2">
<StateGroupIcon stateGroup={state.group} color={state.color} className="h-3 w-3 flex-shrink-0" />
<StateGroupIcon stateGroup={state?.group ?? "backlog"} color={state?.color} className="h-3 w-3 flex-shrink-0" />
<span className="flex-grow truncate">{state?.name}</span>
</div>
),
Expand Down Expand Up @@ -226,22 +234,14 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
{filteredOptions ? (
filteredOptions.length > 0 ? (
filteredOptions.map((option) => (
<Combobox.Option
<StateOption
key={option.value}
value={option.value}
className={({ active, selected }) =>
`flex w-full cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5 ${
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
>
{({ selected }) => (
<>
<span className="flex-grow truncate">{option.content}</span>
{selected && <Check className="h-3.5 w-3.5 flex-shrink-0" />}
</>
)}
</Combobox.Option>
option={option}
projectId={projectId}
filterAvailableStateIds={filterAvailableStateIds}
selectedValue={value}
className="flex w-full cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5"
/>
Comment on lines +237 to +244
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

StateOption integration looks correct but props mismatch detected

The StateOption component in web/ce/components/workflow/state-option.tsx only accepts option and className props, but it's being called with additional props (projectId, filterAvailableStateIds, selectedValue) that aren't used in its implementation. This could lead to potential issues:

  • The component ignores projectId, filterAvailableStateIds, and selectedValue props that are being passed to it
  • If these props are meant to affect the component's behavior, the functionality is currently missing
🔗 Analysis chain

LGTM! Verify StateOption component integration.

The integration of the custom StateOption component looks good. However, let's verify its implementation to ensure it handles all edge cases properly.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check StateOption component implementation
ast-grep --pattern 'export const StateOption = ({ option, projectId, filterAvailableStateIds, selectedValue, className }) => {
  $$$
}'

Length of output: 137


Script:

#!/bin/bash
# Let's try a broader search for StateOption component
ast-grep --pattern 'const StateOption = $_'

# Also search for any file containing StateOption
rg "StateOption" -A 10

Length of output: 4245

))
) : (
<p className="px-1.5 py-1 italic text-custom-text-400">No matches found</p>
Expand Down
Loading