2024-01-24 13:51:59 +00:00
|
|
|
import React, { useState } from "react";
|
2024-01-10 14:39:45 +00:00
|
|
|
import { observer } from "mobx-react-lite";
|
2024-02-21 13:50:46 +00:00
|
|
|
import xor from "lodash/xor";
|
2024-01-10 14:39:45 +00:00
|
|
|
// hooks
|
2024-01-24 13:51:59 +00:00
|
|
|
import { useIssueDetail } from "hooks/store";
|
|
|
|
// components
|
2024-01-31 10:06:55 +00:00
|
|
|
import { ModuleDropdown } from "components/dropdowns";
|
2024-01-10 14:39:45 +00:00
|
|
|
// ui
|
2024-01-24 13:51:59 +00:00
|
|
|
import { Spinner } from "@plane/ui";
|
|
|
|
// helpers
|
|
|
|
import { cn } from "helpers/common.helper";
|
2024-01-10 14:39:45 +00:00
|
|
|
// types
|
|
|
|
import type { TIssueOperations } from "./root";
|
|
|
|
|
|
|
|
type TIssueModuleSelect = {
|
2024-01-24 13:51:59 +00:00
|
|
|
className?: string;
|
2024-01-10 14:39:45 +00:00
|
|
|
workspaceSlug: string;
|
|
|
|
projectId: string;
|
|
|
|
issueId: string;
|
|
|
|
issueOperations: TIssueOperations;
|
|
|
|
disabled?: boolean;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const IssueModuleSelect: React.FC<TIssueModuleSelect> = observer((props) => {
|
2024-01-24 13:51:59 +00:00
|
|
|
const { className = "", workspaceSlug, projectId, issueId, issueOperations, disabled = false } = props;
|
|
|
|
// states
|
|
|
|
const [isUpdating, setIsUpdating] = useState(false);
|
|
|
|
// store hooks
|
2024-01-10 14:39:45 +00:00
|
|
|
const {
|
|
|
|
issue: { getIssueById },
|
|
|
|
} = useIssueDetail();
|
2024-01-24 13:51:59 +00:00
|
|
|
// derived values
|
2024-01-10 14:39:45 +00:00
|
|
|
const issue = getIssueById(issueId);
|
|
|
|
const disableSelect = disabled || isUpdating;
|
|
|
|
|
2024-01-31 10:06:55 +00:00
|
|
|
const handleIssueModuleChange = async (moduleIds: string[]) => {
|
|
|
|
if (!issue || !issue.module_ids) return;
|
2024-01-30 09:53:20 +00:00
|
|
|
|
2024-01-10 14:39:45 +00:00
|
|
|
setIsUpdating(true);
|
2024-02-21 13:50:46 +00:00
|
|
|
const updatedModuleIds = xor(issue.module_ids, moduleIds);
|
|
|
|
const modulesToAdd: string[] = [];
|
|
|
|
const modulesToRemove: string[] = [];
|
2024-01-30 09:53:20 +00:00
|
|
|
|
2024-02-21 13:50:46 +00:00
|
|
|
for (const moduleId of updatedModuleIds) {
|
|
|
|
if (issue.module_ids.includes(moduleId)) {
|
|
|
|
modulesToRemove.push(moduleId);
|
|
|
|
} else {
|
|
|
|
modulesToAdd.push(moduleId);
|
|
|
|
}
|
2024-01-30 09:53:20 +00:00
|
|
|
}
|
2024-02-21 13:50:46 +00:00
|
|
|
if (modulesToRemove.length > 0)
|
|
|
|
await issueOperations.removeModulesFromIssue?.(workspaceSlug, projectId, issueId, modulesToRemove);
|
|
|
|
|
|
|
|
if (modulesToAdd.length > 0)
|
|
|
|
await issueOperations.addModulesToIssue?.(workspaceSlug, projectId, issueId, modulesToAdd);
|
2024-01-31 10:06:55 +00:00
|
|
|
|
2024-01-10 14:39:45 +00:00
|
|
|
setIsUpdating(false);
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2024-01-30 09:53:20 +00:00
|
|
|
<div className={cn(`flex items-center gap-1 h-full`, className)}>
|
2024-01-31 10:06:55 +00:00
|
|
|
<ModuleDropdown
|
2024-01-24 13:51:59 +00:00
|
|
|
projectId={projectId}
|
2024-01-31 10:06:55 +00:00
|
|
|
value={issue?.module_ids ?? []}
|
2024-01-30 09:53:20 +00:00
|
|
|
onChange={handleIssueModuleChange}
|
2024-01-24 13:51:59 +00:00
|
|
|
placeholder="No module"
|
2024-01-30 09:53:20 +00:00
|
|
|
disabled={disableSelect}
|
2024-01-31 10:06:55 +00:00
|
|
|
className="w-full h-full group"
|
2024-01-30 09:53:20 +00:00
|
|
|
buttonContainerClassName="w-full"
|
2024-01-31 10:06:55 +00:00
|
|
|
buttonClassName={`min-h-8 text-sm justify-between ${issue?.module_ids?.length ? "" : "text-custom-text-400"}`}
|
2024-01-30 09:53:20 +00:00
|
|
|
buttonVariant="transparent-with-text"
|
2024-01-31 10:06:55 +00:00
|
|
|
hideIcon
|
|
|
|
dropdownArrow
|
2024-01-24 13:51:59 +00:00
|
|
|
dropdownArrowClassName="h-3.5 w-3.5 hidden group-hover:inline"
|
2024-01-31 10:06:55 +00:00
|
|
|
showTooltip
|
|
|
|
multiple
|
2024-01-24 13:51:59 +00:00
|
|
|
/>
|
2024-01-10 14:39:45 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
});
|