mirror of
https://github.com/makeplane/plane.git
synced 2026-07-12 21:40:18 +02:00
[WEB-3514] improvement: workflow UI (#2713)
* improvement: workflow and reviewer icon padding and styles * improvement: disable reviewer collapsible if no reviewers are available. * minor UI improvements * improvement: workflow tree message
This commit is contained in:
@@ -120,7 +120,9 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
|
||||
>
|
||||
<div className="inline-block line-clamp-1 truncate font-medium text-custom-text-100">{title}</div>
|
||||
<div className="pl-2 text-sm font-medium text-custom-text-300">{count || 0}</div>
|
||||
<WorkFlowGroupTree groupBy={groupBy} groupId={groupID} />
|
||||
<div className="px-2.5">
|
||||
<WorkFlowGroupTree groupBy={groupBy} groupId={groupID} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!disableIssueCreation &&
|
||||
|
||||
@@ -20,7 +20,7 @@ export const StateItemContent = observer((props: StateItemContentProps) => {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-full gap-1.5 p-2">
|
||||
<div className={cn("flex flex-col gap-3 px-3", transitionIds.length > 0 && "py-2")}>
|
||||
<div className={cn("flex flex-col gap-4 px-3", transitionIds.length > 0 && "py-2")}>
|
||||
{transitionIds.map((transitionId) => (
|
||||
<StateTransitionItem
|
||||
key={transitionId}
|
||||
|
||||
@@ -28,8 +28,8 @@ export const StateTransitionApprovers = observer((props: Props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<hr className="border-t-[1px] border-custom-border-200 border-dashed h-[1] w-full pb-2" />
|
||||
<div className="flex flex-col pb-2 gap-1">
|
||||
<hr className="border-t-[1px] border-custom-border-200 border-dashed h-[1] w-full pb-2 mt-1.5" />
|
||||
<div className="flex flex-col pt-1 pb-2 gap-1">
|
||||
<span className="flex items-center gap-1 text-xs text-custom-text-300 font-medium">
|
||||
{t("workflows.workflow_states.state_changes.movers.label")}
|
||||
<Tooltip tooltipContent={t("workflows.workflow_states.state_changes.movers.tooltip")} position="right">
|
||||
@@ -38,7 +38,7 @@ export const StateTransitionApprovers = observer((props: Props) => {
|
||||
</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
<div className="flex p-3 rounded-md border border-custom-border-100 w-full gap-2 items-center">
|
||||
<div className="flex p-3 my-1 rounded-md border border-custom-border-100 w-full gap-2 items-center">
|
||||
<AppliedMembersFilters
|
||||
editable
|
||||
handleRemove={(value) =>
|
||||
|
||||
@@ -38,6 +38,7 @@ export const StateTransitionItem = observer((props: StateTransitionItemProps) =>
|
||||
} = useProjectState();
|
||||
// derived state
|
||||
const stateTransition = getTransitionById(parentStateId, transitionId);
|
||||
const areApproversAvailable = stateTransition.approvers && stateTransition.approvers.length > 0;
|
||||
|
||||
if (!stateTransition) return <></>;
|
||||
|
||||
@@ -47,6 +48,11 @@ export const StateTransitionItem = observer((props: StateTransitionItemProps) =>
|
||||
stateTransition.transition_state_id
|
||||
);
|
||||
|
||||
const handleToggle = () => {
|
||||
if (!areApproversAvailable) return;
|
||||
setIsOpen((prevState) => !prevState);
|
||||
};
|
||||
|
||||
const handleTransitionStateChange = async (val: string) => {
|
||||
try {
|
||||
await changeStateTransition(workspaceSlug, projectId, parentStateId, transitionId, val);
|
||||
@@ -101,9 +107,11 @@ export const StateTransitionItem = observer((props: StateTransitionItemProps) =>
|
||||
/>
|
||||
<Collapsible
|
||||
isOpen={isOpen}
|
||||
onToggle={() => setIsOpen((prevState) => !prevState)}
|
||||
onToggle={handleToggle}
|
||||
className="w-full"
|
||||
buttonClassName="flex w-full items-center justify-between"
|
||||
buttonClassName={cn("flex w-full items-center justify-between", {
|
||||
"cursor-not-allowed": !areApproversAvailable,
|
||||
})}
|
||||
title={
|
||||
<div className="flex w-full items-center">
|
||||
<div className="flex w-full items-center justify-start gap-1 py-1">
|
||||
@@ -126,7 +134,7 @@ export const StateTransitionItem = observer((props: StateTransitionItemProps) =>
|
||||
dropdownArrow
|
||||
/>
|
||||
</div>
|
||||
{stateTransition.approvers && stateTransition.approvers.length > 0 && (
|
||||
{areApproversAvailable && (
|
||||
<div className="flex gap-1 text-custom-text-400 items-center">
|
||||
<ApproverIcon strokeWidth={2} className="flex-shrink-0 size-3.5 text-custom-text-300" />
|
||||
<span className="text-xs font-medium">
|
||||
@@ -167,7 +175,8 @@ export const StateTransitionItem = observer((props: StateTransitionItemProps) =>
|
||||
<ChevronDown
|
||||
strokeWidth={2}
|
||||
className={cn("transition-all size-4 text-custom-text-400 hover:text-custom-text-300", {
|
||||
"rotate-180 text-custom-text-200": isOpen,
|
||||
"rotate-180 text-custom-text-200": isOpen && areApproversAvailable,
|
||||
"text-custom-text-400 hover:text-custom-text-400": !areApproversAvailable,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
@@ -176,11 +185,13 @@ export const StateTransitionItem = observer((props: StateTransitionItemProps) =>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<StateTransitionApprovers
|
||||
parentStateId={parentStateId}
|
||||
stateTransition={stateTransition}
|
||||
handleApproversUpdate={handleApproversUpdate}
|
||||
/>
|
||||
{areApproversAvailable && (
|
||||
<StateTransitionApprovers
|
||||
parentStateId={parentStateId}
|
||||
stateTransition={stateTransition}
|
||||
handleApproversUpdate={handleApproversUpdate}
|
||||
/>
|
||||
)}
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -29,7 +29,7 @@ export const WorkFlowEnabledMessage = observer((props: Props) => {
|
||||
<span className="text-xs font-medium">{t("workflows.workflow_enabled.label")}</span>
|
||||
</div>
|
||||
<div className="pl-4">
|
||||
<WorkflowTree parentStateId={parentStateId} showCurrentUserName={false} />
|
||||
<WorkflowTree parentStateId={parentStateId} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -45,14 +45,14 @@ export const WorkFlowGroupTree = observer((props: Props) => {
|
||||
"flex h-[20px] w-[20px] flex-shrink-0 items-center justify-center overflow-hidden rounded transition-all",
|
||||
{
|
||||
"bg-[#00A0CC]/15": isTransitionEnabledForUser,
|
||||
"hover:bg-custom-background-80": !isTransitionEnabledForUser,
|
||||
"bg-custom-background-80 hover:bg-custom-background-80": !isTransitionEnabledForUser,
|
||||
}
|
||||
)}
|
||||
>
|
||||
{isTransitionEnabledForUser ? (
|
||||
<ApproverIcon width={14} strokeWidth={2} className="text-[#00A0CC]" />
|
||||
) : (
|
||||
<WorkflowIcon width={14} strokeWidth={2} />
|
||||
<WorkflowIcon width={14} strokeWidth={2} className="text-custom-text-200" />
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
@@ -9,11 +9,10 @@ import { StatePill } from "./state-pill";
|
||||
|
||||
type Props = {
|
||||
parentStateId: string;
|
||||
showCurrentUserName?: boolean;
|
||||
};
|
||||
|
||||
export const WorkflowTree = observer((props: Props) => {
|
||||
const { parentStateId, showCurrentUserName = true } = props;
|
||||
const { parentStateId } = props;
|
||||
// plane hooks
|
||||
const { t } = useTranslation();
|
||||
// store hooks
|
||||
@@ -24,7 +23,7 @@ export const WorkflowTree = observer((props: Props) => {
|
||||
const currentStateTransitionMap = stateTransitionMap[parentStateId];
|
||||
|
||||
const getUserName = (moverId: string) => {
|
||||
if (!showCurrentUserName && moverId === user?.id) return t("common.you");
|
||||
if (moverId === user?.id) return t("common.you");
|
||||
return getUserDetails(moverId)?.display_name;
|
||||
};
|
||||
|
||||
@@ -46,15 +45,15 @@ export const WorkflowTree = observer((props: Props) => {
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Order approvers such that current user is first, followed by other approvers
|
||||
// Order approvers such that current user is last
|
||||
const getOrderedApprovers = useCallback(
|
||||
(approvers: string[]) => {
|
||||
const currentUserIndex = approvers.indexOf(user?.id ?? "");
|
||||
if (currentUserIndex !== -1) {
|
||||
return [
|
||||
approvers[currentUserIndex],
|
||||
...approvers.slice(0, currentUserIndex),
|
||||
...approvers.slice(currentUserIndex + 1),
|
||||
approvers[currentUserIndex],
|
||||
];
|
||||
}
|
||||
return approvers;
|
||||
|
||||
Reference in New Issue
Block a user