/** * Copyright (c) 2023-present Plane Software, Inc. and contributors * SPDX-License-Identifier: AGPL-3.0-only * See the LICENSE file for details. */ import React, { forwardRef, useEffect } from "react"; import { observer } from "mobx-react"; import { TwitterPicker } from "react-color"; import type { SubmitHandler } from "react-hook-form"; import { Controller, useForm } from "react-hook-form"; import { Popover, Transition } from "@headlessui/react"; // plane imports import { Field } from "@makeplane/propel/components/field"; import { Input, InputGroup } from "@makeplane/propel/components/input"; import { getRandomLabelColor, LABEL_COLOR_OPTIONS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import type { IIssueLabel } from "@plane/types"; // error codes const errorCodes = { LABEL_NAME_ALREADY_EXISTS: "LABEL_NAME_ALREADY_EXISTS", }; export type TLabelOperationsCallbacks = { createLabel: (data: Partial) => Promise; updateLabel: (labelId: string, data: Partial) => Promise; }; type TCreateUpdateLabelInlineProps = { labelForm: boolean; setLabelForm: React.Dispatch>; isUpdating: boolean; labelOperationsCallbacks: TLabelOperationsCallbacks; labelToUpdate?: IIssueLabel; onClose?: () => void; }; const defaultValues: Partial = { name: "", color: "var(--text-color-secondary)", }; export const CreateUpdateLabelInline = observer( forwardRef(function CreateUpdateLabelInline( props: TCreateUpdateLabelInlineProps, ref: React.ForwardedRef ) { const { labelForm, setLabelForm, isUpdating, labelOperationsCallbacks, labelToUpdate, onClose } = props; // form info const { handleSubmit, control, reset, formState: { errors, isSubmitting }, watch, setValue, setFocus, } = useForm({ defaultValues, }); const { t } = useTranslation(); const handleClose = () => { setLabelForm(false); reset(defaultValues); if (onClose) onClose(); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const getErrorMessage = (error: any, operation: "create" | "update"): string => { const errorData = error ?? {}; const labelError = errorData.name?.includes(errorCodes.LABEL_NAME_ALREADY_EXISTS); if (labelError) { return t("label.create.already_exists"); } // Fallback to general error messages if (operation === "create") { return errorData?.detail ?? errorData?.error ?? t("common.something_went_wrong"); } return errorData?.error ?? t("project_settings.labels.toast.error"); }; const handleLabelCreate: SubmitHandler = async (formData) => { if (isSubmitting) return; await labelOperationsCallbacks .createLabel(formData) .then((_res) => { handleClose(); reset(defaultValues); }) .catch((error) => { const errorMessage = getErrorMessage(error, "create"); setToast({ title: "Error!", type: TOAST_TYPE.ERROR, message: errorMessage, }); reset(formData); }); }; const handleLabelUpdate: SubmitHandler = async (formData) => { if (!labelToUpdate?.id || isSubmitting) return; await labelOperationsCallbacks .updateLabel(labelToUpdate.id, formData) .then((_res) => { reset(defaultValues); handleClose(); }) .catch((error) => { const errorMessage = getErrorMessage(error, "update"); setToast({ title: "Oops!", type: TOAST_TYPE.ERROR, message: errorMessage, }); reset(formData); }); }; const handleFormSubmit = (formData: IIssueLabel) => { if (isUpdating) { handleLabelUpdate(formData); } else { handleLabelCreate(formData); } }; /** * For settings focus on name input */ useEffect(() => { setFocus("name"); }, [setFocus, labelForm]); useEffect(() => { if (!labelToUpdate) return; setValue("name", labelToUpdate.name); setValue("color", labelToUpdate.color && labelToUpdate.color !== "" ? labelToUpdate.color : "#000"); }, [labelToUpdate, setValue]); useEffect(() => { if (labelToUpdate) { setValue("color", labelToUpdate.color && labelToUpdate.color !== "" ? labelToUpdate.color : "#000"); return; } setValue("color", getRandomLabelColor()); }, [labelToUpdate, setValue]); return ( <>
{({ open }) => ( <> ( onChange(value.hex)} /> )} /> )}
( )} />
{errors.name?.message &&

{errors.name?.message}

} ); }) );