forked from github/plane
[WEB-570] chore: toast refactor (#3836)
* new toast setup * chore: new toast implementation. * chore: move toast component to ui package. * chore: replace `setToast` with `setPromiseToast` in required places for better UX. * chore: code cleanup. * chore: update theme. * fix: theme switching issue. * chore: remove toast from issue update operations. * chore: add promise toast for add/ remove issue to cycle/ module and remove local spinners. --------- Co-authored-by: rahulramesha <rahulramesham@gmail.com>
This commit is contained in:
parent
c06ef4d1d7
commit
53367a6bc4
@ -198,6 +198,31 @@ module.exports = {
|
||||
300: convertToRGB("--color-onboarding-border-300"),
|
||||
},
|
||||
},
|
||||
toast: {
|
||||
text: {
|
||||
success: convertToRGB("--color-toast-success-text"),
|
||||
error: convertToRGB("--color-toast-error-text"),
|
||||
warning: convertToRGB("--color-toast-warning-text"),
|
||||
info: convertToRGB("--color-toast-info-text"),
|
||||
loading: convertToRGB("--color-toast-loading-text"),
|
||||
secondary: convertToRGB("--color-toast-secondary-text"),
|
||||
tertiary: convertToRGB("--color-toast-tertiary-text"),
|
||||
},
|
||||
background: {
|
||||
success: convertToRGB("--color-toast-success-background"),
|
||||
error: convertToRGB("--color-toast-error-background"),
|
||||
warning: convertToRGB("--color-toast-warning-background"),
|
||||
info: convertToRGB("--color-toast-info-background"),
|
||||
loading: convertToRGB("--color-toast-loading-background"),
|
||||
},
|
||||
border: {
|
||||
success: convertToRGB("--color-toast-success-border"),
|
||||
error: convertToRGB("--color-toast-error-border"),
|
||||
warning: convertToRGB("--color-toast-warning-border"),
|
||||
info: convertToRGB("--color-toast-info-border"),
|
||||
loading: convertToRGB("--color-toast-loading-border"),
|
||||
},
|
||||
},
|
||||
},
|
||||
keyframes: {
|
||||
leftToaster: {
|
||||
|
@ -26,6 +26,7 @@
|
||||
"react-color": "^2.19.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-popper": "^2.3.0",
|
||||
"sonner": "^1.4.2",
|
||||
"tailwind-merge": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -10,3 +10,4 @@ export * from "./spinners";
|
||||
export * from "./tooltip";
|
||||
export * from "./loader";
|
||||
export * from "./control-link";
|
||||
export * from "./toast";
|
||||
|
35
packages/ui/src/spinners/circular-bar-spinner.tsx
Normal file
35
packages/ui/src/spinners/circular-bar-spinner.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import * as React from "react";
|
||||
|
||||
interface ICircularBarSpinner extends React.SVGAttributes<SVGElement> {
|
||||
height?: string;
|
||||
width?: string;
|
||||
className?: string | undefined;
|
||||
}
|
||||
|
||||
export const CircularBarSpinner: React.FC<ICircularBarSpinner> = ({
|
||||
height = "16px",
|
||||
width = "16px",
|
||||
className = "",
|
||||
}) => (
|
||||
<div role="status">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={width} height={height} viewBox="0 0 24 24" className={className}>
|
||||
<g>
|
||||
<rect width={2} height={5} x={11} y={1} fill="currentColor" opacity={0.14} />
|
||||
<rect width={2} height={5} x={11} y={1} fill="currentColor" opacity={0.29} transform="rotate(30 12 12)" />
|
||||
<rect width={2} height={5} x={11} y={1} fill="currentColor" opacity={0.43} transform="rotate(60 12 12)" />
|
||||
<rect width={2} height={5} x={11} y={1} fill="currentColor" opacity={0.57} transform="rotate(90 12 12)" />
|
||||
<rect width={2} height={5} x={11} y={1} fill="currentColor" opacity={0.71} transform="rotate(120 12 12)" />
|
||||
<rect width={2} height={5} x={11} y={1} fill="currentColor" opacity={0.86} transform="rotate(150 12 12)" />
|
||||
<rect width={2} height={5} x={11} y={1} fill="currentColor" transform="rotate(180 12 12)" />
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
calcMode="discrete"
|
||||
dur="0.75s"
|
||||
repeatCount="indefinite"
|
||||
type="rotate"
|
||||
values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
@ -1 +1,2 @@
|
||||
export * from "./circular-spinner";
|
||||
export * from "./circular-bar-spinner";
|
||||
|
206
packages/ui/src/toast/index.tsx
Normal file
206
packages/ui/src/toast/index.tsx
Normal file
@ -0,0 +1,206 @@
|
||||
import * as React from "react";
|
||||
import { Toaster, toast } from "sonner";
|
||||
// icons
|
||||
import { AlertTriangle, CheckCircle2, X, XCircle } from "lucide-react";
|
||||
// spinner
|
||||
import { CircularBarSpinner } from "../spinners";
|
||||
// helper
|
||||
import { cn } from "../../helpers";
|
||||
|
||||
export enum TOAST_TYPE {
|
||||
SUCCESS = "success",
|
||||
ERROR = "error",
|
||||
INFO = "info",
|
||||
WARNING = "warning",
|
||||
LOADING = "loading",
|
||||
}
|
||||
|
||||
type SetToastProps =
|
||||
| {
|
||||
type: TOAST_TYPE.LOADING;
|
||||
title?: string;
|
||||
}
|
||||
| {
|
||||
id?: string | number;
|
||||
type: Exclude<TOAST_TYPE, TOAST_TYPE.LOADING>;
|
||||
title: string;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
type PromiseToastCallback<ToastData> = (data: ToastData) => string;
|
||||
|
||||
type PromiseToastData<ToastData> = {
|
||||
title: string;
|
||||
message?: PromiseToastCallback<ToastData>;
|
||||
};
|
||||
|
||||
type PromiseToastOptions<ToastData> = {
|
||||
loading?: string;
|
||||
success: PromiseToastData<ToastData>;
|
||||
error: PromiseToastData<ToastData>;
|
||||
};
|
||||
|
||||
type ToastContentProps = {
|
||||
toastId: string | number;
|
||||
icon?: React.ReactNode;
|
||||
textColorClassName: string;
|
||||
backgroundColorClassName: string;
|
||||
borderColorClassName: string;
|
||||
};
|
||||
|
||||
type ToastProps = {
|
||||
theme: "light" | "dark" | "system";
|
||||
};
|
||||
|
||||
export const Toast = (props: ToastProps) => {
|
||||
const { theme } = props;
|
||||
return <Toaster visibleToasts={5} gap={20} theme={theme} />;
|
||||
};
|
||||
|
||||
export const setToast = (props: SetToastProps) => {
|
||||
const renderToastContent = ({
|
||||
toastId,
|
||||
icon,
|
||||
textColorClassName,
|
||||
backgroundColorClassName,
|
||||
borderColorClassName,
|
||||
}: ToastContentProps) =>
|
||||
props.type === TOAST_TYPE.LOADING ? (
|
||||
<div
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
className={cn("w-[350px] h-[67.3px] rounded-lg border shadow-sm p-2", backgroundColorClassName, borderColorClassName)}
|
||||
>
|
||||
<div className="w-full h-full flex items-center justify-center px-4 py-2">
|
||||
{icon && <div className="flex items-center justify-center">{icon}</div>}
|
||||
<div className={cn("w-full flex items-center gap-0.5 pr-1", icon ? "pl-4" : "pl-1")}>
|
||||
<div className={cn("grow text-sm font-semibold", textColorClassName)}>{props.title ?? "Loading..."}</div>
|
||||
<div className="flex-shrink-0">
|
||||
<X
|
||||
className="text-toast-text-secondary hover:text-toast-text-tertiary cursor-pointer"
|
||||
strokeWidth={1.5}
|
||||
width={14}
|
||||
height={14}
|
||||
onClick={() => toast.dismiss(toastId)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
className={cn(
|
||||
"relative flex flex-col w-[350px] rounded-lg border shadow-sm p-2",
|
||||
backgroundColorClassName,
|
||||
borderColorClassName
|
||||
)}
|
||||
>
|
||||
<X
|
||||
className="fixed top-2 right-2.5 text-toast-text-secondary hover:text-toast-text-tertiary cursor-pointer"
|
||||
strokeWidth={1.5}
|
||||
width={14}
|
||||
height={14}
|
||||
onClick={() => toast.dismiss(toastId)}
|
||||
/>
|
||||
<div className="w-full flex items-center px-4 py-2">
|
||||
{icon && <div className="flex items-center justify-center">{icon}</div>}
|
||||
<div className={cn("flex flex-col gap-0.5 pr-1", icon ? "pl-6" : "pl-1")}>
|
||||
<div className={cn("text-sm font-semibold", textColorClassName)}>{props.title}</div>
|
||||
{props.message && <div className="text-toast-text-secondary text-xs font-medium">{props.message}</div>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
switch (props.type) {
|
||||
case TOAST_TYPE.SUCCESS:
|
||||
return toast.custom(
|
||||
(toastId) =>
|
||||
renderToastContent({
|
||||
toastId,
|
||||
icon: <CheckCircle2 width={28} height={28} strokeWidth={1.5} className="text-toast-text-success" />,
|
||||
textColorClassName: "text-toast-text-success",
|
||||
backgroundColorClassName: "bg-toast-background-success",
|
||||
borderColorClassName: "border-toast-border-success",
|
||||
}),
|
||||
props.id ? { id: props.id } : {}
|
||||
);
|
||||
case TOAST_TYPE.ERROR:
|
||||
return toast.custom(
|
||||
(toastId) =>
|
||||
renderToastContent({
|
||||
toastId,
|
||||
icon: <XCircle width={28} height={28} strokeWidth={1.5} className="text-toast-text-error" />,
|
||||
textColorClassName: "text-toast-text-error",
|
||||
backgroundColorClassName: "bg-toast-background-error",
|
||||
borderColorClassName: "border-toast-border-error",
|
||||
}),
|
||||
props.id ? { id: props.id } : {}
|
||||
);
|
||||
case TOAST_TYPE.WARNING:
|
||||
return toast.custom(
|
||||
(toastId) =>
|
||||
renderToastContent({
|
||||
toastId,
|
||||
icon: <AlertTriangle width={28} height={28} strokeWidth={1.5} className="text-toast-text-warning" />,
|
||||
textColorClassName: "text-toast-text-warning",
|
||||
backgroundColorClassName: "bg-toast-background-warning",
|
||||
borderColorClassName: "border-toast-border-warning",
|
||||
}),
|
||||
props.id ? { id: props.id } : {}
|
||||
);
|
||||
case TOAST_TYPE.INFO:
|
||||
return toast.custom(
|
||||
(toastId) =>
|
||||
renderToastContent({
|
||||
toastId,
|
||||
textColorClassName: "text-toast-text-info",
|
||||
backgroundColorClassName: "bg-toast-background-info",
|
||||
borderColorClassName: "border-toast-border-info",
|
||||
}),
|
||||
props.id ? { id: props.id } : {}
|
||||
);
|
||||
|
||||
case TOAST_TYPE.LOADING:
|
||||
return toast.custom((toastId) =>
|
||||
renderToastContent({
|
||||
toastId,
|
||||
icon: <CircularBarSpinner className="text-toast-text-tertiary" />,
|
||||
textColorClassName: "text-toast-text-loading",
|
||||
backgroundColorClassName: "bg-toast-background-loading",
|
||||
borderColorClassName: "border-toast-border-loading",
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const setPromiseToast = <ToastData,>(
|
||||
promise: Promise<ToastData>,
|
||||
options: PromiseToastOptions<ToastData>
|
||||
): void => {
|
||||
const tId = setToast({ type: TOAST_TYPE.LOADING, title: options.loading });
|
||||
|
||||
promise
|
||||
.then((data: ToastData) => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
id: tId,
|
||||
title: options.success.title,
|
||||
message: options.success.message?.(data),
|
||||
});
|
||||
})
|
||||
.catch((data: ToastData) => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
id: tId,
|
||||
title: options.error.title,
|
||||
message: options.error.message?.(data),
|
||||
});
|
||||
});
|
||||
};
|
@ -7,9 +7,7 @@ import { mutate } from "swr";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -26,7 +24,6 @@ export const DeactivateAccountModal: React.FC<Props> = (props) => {
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
const handleClose = () => {
|
||||
@ -39,8 +36,8 @@ export const DeactivateAccountModal: React.FC<Props> = (props) => {
|
||||
|
||||
await deactivateAccount()
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Account deactivated successfully.",
|
||||
});
|
||||
@ -50,8 +47,8 @@ export const DeactivateAccountModal: React.FC<Props> = (props) => {
|
||||
handleClose();
|
||||
})
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error,
|
||||
})
|
||||
@ -90,7 +87,10 @@ export const DeactivateAccountModal: React.FC<Props> = (props) => {
|
||||
<div className="">
|
||||
<div className="flex items-start gap-x-4">
|
||||
<div className="grid place-items-center rounded-full bg-red-500/20 p-2 sm:p-2 md:p-4 lg:p-4 mt-3 sm:mt-3 md:mt-0 lg:mt-0 ">
|
||||
<Trash2 className="h-4 w-4 sm:h-4 sm:w-4 md:h-6 md:w-6 lg:h-6 lg:w-6 text-red-600" aria-hidden="true" />
|
||||
<Trash2
|
||||
className="h-4 w-4 sm:h-4 sm:w-4 md:h-6 md:w-6 lg:h-6 lg:w-6 text-red-600"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Dialog.Title as="h3" className="my-4 text-2xl font-medium leading-6 text-custom-text-100">
|
||||
|
@ -3,7 +3,8 @@ import { observer } from "mobx-react-lite";
|
||||
import { AuthService } from "services/auth.service";
|
||||
// hooks
|
||||
import { useApplication } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { GitHubSignInButton, GoogleSignInButton } from "components/account";
|
||||
|
||||
@ -17,8 +18,6 @@ const authService = new AuthService();
|
||||
|
||||
export const OAuthOptions: React.FC<Props> = observer((props) => {
|
||||
const { handleSignInRedirection, type } = props;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// mobx store
|
||||
const {
|
||||
config: { envConfig },
|
||||
@ -39,9 +38,9 @@ export const OAuthOptions: React.FC<Props> = observer((props) => {
|
||||
if (response) handleSignInRedirection();
|
||||
} else throw Error("Cant find credentials");
|
||||
} catch (err: any) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error signing in!",
|
||||
type: "error",
|
||||
message: err?.error || "Something went wrong. Please try again later or contact the support team.",
|
||||
});
|
||||
}
|
||||
@ -60,9 +59,9 @@ export const OAuthOptions: React.FC<Props> = observer((props) => {
|
||||
if (response) handleSignInRedirection();
|
||||
} else throw Error("Cant find credentials");
|
||||
} catch (err: any) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error signing in!",
|
||||
type: "error",
|
||||
message: err?.error || "Something went wrong. Please try again later or contact the support team.",
|
||||
});
|
||||
}
|
||||
|
@ -4,10 +4,8 @@ import { XCircle } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// services
|
||||
import { AuthService } from "services/auth.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// types
|
||||
@ -27,7 +25,6 @@ const authService = new AuthService();
|
||||
export const SignInEmailForm: React.FC<Props> = observer((props) => {
|
||||
const { onSubmit, updateEmail } = props;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
control,
|
||||
formState: { errors, isSubmitting, isValid },
|
||||
@ -52,8 +49,8 @@ export const SignInEmailForm: React.FC<Props> = observer((props) => {
|
||||
.emailCheck(payload)
|
||||
.then((res) => onSubmit(res.is_password_autoset))
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -3,10 +3,9 @@ import { Controller, useForm } from "react-hook-form";
|
||||
// services
|
||||
import { AuthService } from "services/auth.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker } from "hooks/store";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// icons
|
||||
@ -38,8 +37,6 @@ export const SignInOptionalSetPasswordForm: React.FC<Props> = (props) => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// store hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// form info
|
||||
const {
|
||||
control,
|
||||
@ -62,8 +59,8 @@ export const SignInOptionalSetPasswordForm: React.FC<Props> = (props) => {
|
||||
await authService
|
||||
.setPassword(payload)
|
||||
.then(async () => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Password created successfully.",
|
||||
});
|
||||
@ -78,8 +75,8 @@ export const SignInOptionalSetPasswordForm: React.FC<Props> = (props) => {
|
||||
state: "FAILED",
|
||||
first_time: false,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
});
|
||||
|
@ -6,12 +6,11 @@ import { Eye, EyeOff, XCircle } from "lucide-react";
|
||||
// services
|
||||
import { AuthService } from "services/auth.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useApplication, useEventTracker } from "hooks/store";
|
||||
// components
|
||||
import { ESignInSteps, ForgotPasswordPopover } from "components/account";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// types
|
||||
@ -43,8 +42,6 @@ export const SignInPasswordForm: React.FC<Props> = observer((props) => {
|
||||
// states
|
||||
const [isSendingUniqueCode, setIsSendingUniqueCode] = useState(false);
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
config: { envConfig },
|
||||
} = useApplication();
|
||||
@ -83,8 +80,8 @@ export const SignInPasswordForm: React.FC<Props> = observer((props) => {
|
||||
await onSubmit();
|
||||
})
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
@ -107,8 +104,8 @@ export const SignInPasswordForm: React.FC<Props> = observer((props) => {
|
||||
.generateUniqueCode({ email: emailFormValue })
|
||||
.then(() => handleStepChange(ESignInSteps.USE_UNIQUE_CODE_FROM_PASSWORD))
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -5,11 +5,10 @@ import { XCircle } from "lucide-react";
|
||||
import { AuthService } from "services/auth.service";
|
||||
import { UserService } from "services/user.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useTimer from "hooks/use-timer";
|
||||
import { useEventTracker } from "hooks/store";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// types
|
||||
@ -42,8 +41,6 @@ export const SignInUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
const { email, onSubmit, handleEmailClear, submitButtonText } = props;
|
||||
// states
|
||||
const [isRequestingNewCode, setIsRequestingNewCode] = useState(false);
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// store hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
// timer
|
||||
@ -84,8 +81,8 @@ export const SignInUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
captureEvent(CODE_VERIFIED, {
|
||||
state: "FAILED",
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
});
|
||||
@ -101,8 +98,8 @@ export const SignInUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
.generateUniqueCode(payload)
|
||||
.then(() => {
|
||||
setResendCodeTimer(30);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "A new unique code has been sent to your email.",
|
||||
});
|
||||
@ -113,8 +110,8 @@ export const SignInUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
});
|
||||
})
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -4,10 +4,8 @@ import { XCircle } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// services
|
||||
import { AuthService } from "services/auth.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// types
|
||||
@ -27,7 +25,6 @@ const authService = new AuthService();
|
||||
export const SignUpEmailForm: React.FC<Props> = observer((props) => {
|
||||
const { onSubmit, updateEmail } = props;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
control,
|
||||
formState: { errors, isSubmitting, isValid },
|
||||
@ -52,8 +49,8 @@ export const SignUpEmailForm: React.FC<Props> = observer((props) => {
|
||||
.emailCheck(payload)
|
||||
.then(() => onSubmit())
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -3,14 +3,14 @@ import { Controller, useForm } from "react-hook-form";
|
||||
// services
|
||||
import { AuthService } from "services/auth.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker } from "hooks/store";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// constants
|
||||
// components
|
||||
import { ESignUpSteps } from "components/account";
|
||||
// constants
|
||||
import { PASSWORD_CREATE_SELECTED, PASSWORD_CREATE_SKIPPED, SETUP_PASSWORD } from "constants/event-tracker";
|
||||
// icons
|
||||
import { Eye, EyeOff } from "lucide-react";
|
||||
@ -41,8 +41,6 @@ export const SignUpOptionalSetPasswordForm: React.FC<Props> = (props) => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// store hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// form info
|
||||
const {
|
||||
control,
|
||||
@ -65,8 +63,8 @@ export const SignUpOptionalSetPasswordForm: React.FC<Props> = (props) => {
|
||||
await authService
|
||||
.setPassword(payload)
|
||||
.then(async () => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Password created successfully.",
|
||||
});
|
||||
@ -81,8 +79,8 @@ export const SignUpOptionalSetPasswordForm: React.FC<Props> = (props) => {
|
||||
state: "FAILED",
|
||||
first_time: true,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
});
|
||||
|
@ -5,10 +5,8 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { Eye, EyeOff, XCircle } from "lucide-react";
|
||||
// services
|
||||
import { AuthService } from "services/auth.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// types
|
||||
@ -34,8 +32,6 @@ export const SignUpPasswordForm: React.FC<Props> = observer((props) => {
|
||||
const { onSubmit } = props;
|
||||
// states
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// form info
|
||||
const {
|
||||
control,
|
||||
@ -59,8 +55,8 @@ export const SignUpPasswordForm: React.FC<Props> = observer((props) => {
|
||||
.passwordSignIn(payload)
|
||||
.then(async () => await onSubmit())
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -6,11 +6,10 @@ import { XCircle } from "lucide-react";
|
||||
import { AuthService } from "services/auth.service";
|
||||
import { UserService } from "services/user.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useTimer from "hooks/use-timer";
|
||||
import { useEventTracker } from "hooks/store";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
// types
|
||||
@ -44,8 +43,6 @@ export const SignUpUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
const [isRequestingNewCode, setIsRequestingNewCode] = useState(false);
|
||||
// store hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// timer
|
||||
const { timer: resendTimerCode, setTimer: setResendCodeTimer } = useTimer(30);
|
||||
// form info
|
||||
@ -84,8 +81,8 @@ export const SignUpUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
captureEvent(CODE_VERIFIED, {
|
||||
state: "FAILED",
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
});
|
||||
@ -101,8 +98,8 @@ export const SignUpUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
.generateUniqueCode(payload)
|
||||
.then(() => {
|
||||
setResendCodeTimer(30);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "A new unique code has been sent to your email.",
|
||||
});
|
||||
@ -112,8 +109,8 @@ export const SignUpUniqueCodeForm: React.FC<Props> = (props) => {
|
||||
});
|
||||
})
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -6,11 +6,10 @@ import { mutate } from "swr";
|
||||
import { AnalyticsService } from "services/analytics.service";
|
||||
// hooks
|
||||
import { useCycle, useModule, useProject, useUser, useWorkspace } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { CustomAnalyticsSidebarHeader, CustomAnalyticsSidebarProjectsList } from "components/analytics";
|
||||
// ui
|
||||
import { Button, LayersIcon } from "@plane/ui";
|
||||
import { Button, LayersIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { CalendarDays, Download, RefreshCw } from "lucide-react";
|
||||
// helpers
|
||||
@ -34,8 +33,6 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// store hooks
|
||||
const { currentUser } = useUser();
|
||||
const { workspaceProjectIds, getProjectById } = useProject();
|
||||
@ -107,8 +104,8 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
|
||||
analyticsService
|
||||
.exportAnalytics(workspaceSlug.toString(), data)
|
||||
.then((res) => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: res.message,
|
||||
});
|
||||
@ -116,8 +113,8 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer((props) => {
|
||||
trackExportAnalytics();
|
||||
})
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "There was some error in exporting the analytics. Please try again.",
|
||||
})
|
||||
|
@ -4,10 +4,8 @@ import { mutate } from "swr";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import { APITokenService } from "services/api_token.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IApiToken } from "@plane/types";
|
||||
// fetch-keys
|
||||
@ -25,8 +23,6 @@ export const DeleteApiTokenModal: FC<Props> = (props) => {
|
||||
const { isOpen, onClose, tokenId } = props;
|
||||
// states
|
||||
const [deleteLoading, setDeleteLoading] = useState<boolean>(false);
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
@ -44,8 +40,8 @@ export const DeleteApiTokenModal: FC<Props> = (props) => {
|
||||
apiTokenService
|
||||
.deleteApiToken(workspaceSlug.toString(), tokenId)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Token deleted successfully.",
|
||||
});
|
||||
@ -59,8 +55,8 @@ export const DeleteApiTokenModal: FC<Props> = (props) => {
|
||||
handleClose();
|
||||
})
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error",
|
||||
message: err?.message ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -4,8 +4,8 @@ import { mutate } from "swr";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import { APITokenService } from "services/api_token.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { CreateApiTokenForm, GeneratedTokenDetails } from "components/api-token";
|
||||
// helpers
|
||||
@ -32,8 +32,6 @@ export const CreateApiTokenModal: React.FC<Props> = (props) => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
@ -76,10 +74,10 @@ export const CreateApiTokenModal: React.FC<Props> = (props) => {
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
setToastAlert({
|
||||
message: err.message,
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error",
|
||||
message: err.message,
|
||||
});
|
||||
|
||||
throw err;
|
||||
|
@ -3,10 +3,8 @@ import { add } from "date-fns";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { DateDropdown } from "components/dropdowns";
|
||||
import { Calendar } from "lucide-react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, CustomSelect, Input, TextArea, ToggleSwitch } from "@plane/ui";
|
||||
import { Button, CustomSelect, Input, TextArea, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderFormattedDate, renderFormattedPayloadDate } from "helpers/date-time.helper";
|
||||
// types
|
||||
@ -66,8 +64,6 @@ export const CreateApiTokenForm: React.FC<Props> = (props) => {
|
||||
const { handleClose, neverExpires, toggleNeverExpires, onSubmit } = props;
|
||||
// states
|
||||
const [customDate, setCustomDate] = useState<Date | null>(null);
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// form
|
||||
const {
|
||||
control,
|
||||
@ -80,8 +76,8 @@ export const CreateApiTokenForm: React.FC<Props> = (props) => {
|
||||
const handleFormSubmit = async (data: IApiToken) => {
|
||||
// if never expires is toggled off, and the user has not selected a custom date or a predefined date, show an error
|
||||
if (!neverExpires && (!data.expired_at || (data.expired_at === "custom" && !customDate)))
|
||||
return setToastAlert({
|
||||
type: "error",
|
||||
return setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Please select an expiration date.",
|
||||
});
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { Copy } from "lucide-react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, Tooltip } from "@plane/ui";
|
||||
import { Button, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderFormattedDate } from "helpers/date-time.helper";
|
||||
import { copyTextToClipboard } from "helpers/string.helper";
|
||||
@ -17,12 +15,10 @@ type Props = {
|
||||
export const GeneratedTokenDetails: React.FC<Props> = (props) => {
|
||||
const { handleClose, tokenDetails } = props;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const copyApiToken = (token: string) => {
|
||||
copyTextToClipboard(token).then(() =>
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Token copied to clipboard.",
|
||||
})
|
||||
|
@ -4,10 +4,8 @@ import { Command } from "cmdk";
|
||||
import { LinkIcon, Signal, Trash2, UserMinus2, UserPlus2 } from "lucide-react";
|
||||
// hooks
|
||||
import { useApplication, useUser, useIssues } from "hooks/store";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { DoubleCircleIcon, UserGroupIcon } from "@plane/ui";
|
||||
import { DoubleCircleIcon, UserGroupIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { copyTextToClipboard } from "helpers/string.helper";
|
||||
// types
|
||||
@ -37,8 +35,6 @@ export const CommandPaletteIssueActions: React.FC<Props> = observer((props) => {
|
||||
} = useApplication();
|
||||
const { currentUser } = useUser();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleUpdateIssue = async (formData: Partial<TIssue>) => {
|
||||
if (!workspaceSlug || !projectId || !issueDetails) return;
|
||||
|
||||
@ -71,14 +67,14 @@ export const CommandPaletteIssueActions: React.FC<Props> = observer((props) => {
|
||||
const url = new URL(window.location.href);
|
||||
copyTextToClipboard(url.href)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Copied to clipboard",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Some error occurred",
|
||||
});
|
||||
});
|
||||
|
@ -5,7 +5,8 @@ import { Settings } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// constants
|
||||
import { THEME_OPTIONS } from "constants/themes";
|
||||
|
||||
@ -21,15 +22,14 @@ export const CommandPaletteThemeActions: FC<Props> = observer((props) => {
|
||||
const { updateCurrentUserTheme } = useUser();
|
||||
// hooks
|
||||
const { setTheme } = useTheme();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const updateUserTheme = async (newTheme: string) => {
|
||||
setTheme(newTheme);
|
||||
|
||||
return updateCurrentUserTheme(newTheme).catch(() => {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Failed to save user theme settings!",
|
||||
type: "error",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -4,7 +4,8 @@ import useSWR from "swr";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useApplication, useEventTracker, useIssues, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { CommandModal, ShortcutsModal } from "components/command-palette";
|
||||
import { BulkDeleteIssuesModal } from "components/core";
|
||||
@ -63,8 +64,6 @@ export const CommandPalette: FC = observer(() => {
|
||||
createIssueStoreType,
|
||||
} = commandPalette;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { data: issueDetails } = useSWR(
|
||||
workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId as string) : null,
|
||||
workspaceSlug && projectId && issueId
|
||||
@ -78,18 +77,18 @@ export const CommandPalette: FC = observer(() => {
|
||||
const url = new URL(window.location.href);
|
||||
copyTextToClipboard(url.href)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Copied to clipboard",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Some error occurred",
|
||||
});
|
||||
});
|
||||
}, [setToastAlert, issueId]);
|
||||
}, [issueId]);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
|
@ -6,10 +6,8 @@ import { SubmitHandler, useForm } from "react-hook-form";
|
||||
import { Combobox, Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import { IssueService } from "services/issue";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, LayersIcon } from "@plane/ui";
|
||||
import { Button, LayersIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { Search } from "lucide-react";
|
||||
// types
|
||||
@ -55,8 +53,6 @@ export const BulkDeleteIssuesModal: React.FC<Props> = observer((props) => {
|
||||
: null
|
||||
);
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
watch,
|
||||
@ -79,8 +75,8 @@ export const BulkDeleteIssuesModal: React.FC<Props> = observer((props) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
if (!data.delete_issue_ids || data.delete_issue_ids.length === 0) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Please select at least one issue.",
|
||||
});
|
||||
@ -91,16 +87,16 @@ export const BulkDeleteIssuesModal: React.FC<Props> = observer((props) => {
|
||||
|
||||
await removeBulkIssues(workspaceSlug as string, projectId as string, data.delete_issue_ids)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Issues deleted successfully!",
|
||||
});
|
||||
handleClose();
|
||||
})
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -3,11 +3,9 @@ import { Combobox, Dialog, Transition } from "@headlessui/react";
|
||||
import { Rocket, Search, X } from "lucide-react";
|
||||
// services
|
||||
import { ProjectService } from "services/project";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import useDebounce from "hooks/use-debounce";
|
||||
// ui
|
||||
import { Button, LayersIcon, Loader, ToggleSwitch, Tooltip } from "@plane/ui";
|
||||
import { Button, LayersIcon, Loader, ToggleSwitch, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { ISearchIssueResponse, TProjectIssuesSearchParams } from "@plane/types";
|
||||
|
||||
@ -43,8 +41,6 @@ export const ExistingIssuesListModal: React.FC<Props> = (props) => {
|
||||
|
||||
const debouncedSearchTerm: string = useDebounce(searchTerm, 500);
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
setSearchTerm("");
|
||||
@ -54,8 +50,8 @@ export const ExistingIssuesListModal: React.FC<Props> = (props) => {
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (selectedIssues.length === 0) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Please select at least one issue.",
|
||||
});
|
||||
@ -69,9 +65,9 @@ export const ExistingIssuesListModal: React.FC<Props> = (props) => {
|
||||
|
||||
handleClose();
|
||||
|
||||
setToastAlert({
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success",
|
||||
type: "success",
|
||||
message: `Issue${selectedIssues.length > 1 ? "s" : ""} added successfully`,
|
||||
});
|
||||
};
|
||||
|
@ -3,10 +3,9 @@ import { useRouter } from "next/router";
|
||||
import { Controller, useForm } from "react-hook-form"; // services
|
||||
import { AIService } from "services/ai.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { usePopper } from "react-popper";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { RichReadOnlyEditorWithRef } from "@plane/rich-text-editor";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
@ -44,8 +43,6 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// popper
|
||||
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||
placement: placement ?? "auto",
|
||||
@ -78,8 +75,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
? error || "You have reached the maximum number of requests of 50 requests per month per user."
|
||||
: error || "Some error occurred. Please try again.";
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: errorMessage,
|
||||
});
|
||||
@ -104,8 +101,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
};
|
||||
|
||||
const handleInvalidTask = () => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Please enter some task to get AI assistance.",
|
||||
});
|
||||
|
@ -6,10 +6,8 @@ import { Transition, Dialog } from "@headlessui/react";
|
||||
import { useApplication } from "hooks/store";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { UserCircle2 } from "lucide-react";
|
||||
// constants
|
||||
@ -32,8 +30,6 @@ export const UserImageUploadModal: React.FC<Props> = observer((props) => {
|
||||
// states
|
||||
const [image, setImage] = useState<File | null>(null);
|
||||
const [isImageUploading, setIsImageUploading] = useState(false);
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// store hooks
|
||||
const {
|
||||
config: { envConfig },
|
||||
@ -76,8 +72,8 @@ export const UserImageUploadModal: React.FC<Props> = observer((props) => {
|
||||
if (value) fileService.deleteUserFile(value);
|
||||
})
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -7,10 +7,8 @@ import { Transition, Dialog } from "@headlessui/react";
|
||||
import { useApplication, useWorkspace } from "hooks/store";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { UserCircle2 } from "lucide-react";
|
||||
// constants
|
||||
@ -37,8 +35,6 @@ export const WorkspaceImageUploadModal: React.FC<Props> = observer((props) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const {
|
||||
config: { envConfig },
|
||||
} = useApplication();
|
||||
@ -83,8 +79,8 @@ export const WorkspaceImageUploadModal: React.FC<Props> = observer((props) => {
|
||||
if (value && currentWorkspace) fileService.deleteFile(currentWorkspace.id, value);
|
||||
})
|
||||
.catch((err) =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ui
|
||||
import { ExternalLinkIcon, Tooltip } from "@plane/ui";
|
||||
import { ExternalLinkIcon, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { Pencil, Trash2, LinkIcon } from "lucide-react";
|
||||
// helpers
|
||||
@ -7,7 +7,6 @@ import { calculateTimeAgo } from "helpers/date-time.helper";
|
||||
// types
|
||||
import { ILinkDetails, UserAuth } from "@plane/types";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { observer } from "mobx-react";
|
||||
import { useMeasure } from "@nivo/core";
|
||||
import { useMember } from "hooks/store";
|
||||
@ -20,18 +19,16 @@ type Props = {
|
||||
};
|
||||
|
||||
export const LinksList: React.FC<Props> = observer(({ links, handleDeleteLink, handleEditLink, userAuth }) => {
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
const { getUserDetails } = useMember();
|
||||
|
||||
const isNotAllowed = userAuth.isGuest || userAuth.isViewer;
|
||||
|
||||
const copyToClipboard = (text: string) => {
|
||||
navigator.clipboard.writeText(text);
|
||||
setToastAlert({
|
||||
message: "The URL has been successfully copied to your clipboard",
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Copied to clipboard",
|
||||
message: "The URL has been successfully copied to your clipboard",
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,6 @@ import useSWR from "swr";
|
||||
import { useTheme } from "next-themes";
|
||||
// hooks
|
||||
import { useCycle, useIssues, useMember, useProject, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { SingleProgressStats } from "components/core";
|
||||
import {
|
||||
@ -18,6 +17,7 @@ import {
|
||||
PriorityIcon,
|
||||
Avatar,
|
||||
CycleGroupIcon,
|
||||
setPromiseToast,
|
||||
} from "@plane/ui";
|
||||
// components
|
||||
import ProgressChart from "components/core/sidebar/progress-chart";
|
||||
@ -60,8 +60,6 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
|
||||
} = useCycle();
|
||||
const { currentProjectDetails } = useProject();
|
||||
const { getUserDetails } = useMember();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { isLoading } = useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_ACTIVE_CYCLE_${projectId}` : null,
|
||||
@ -119,12 +117,18 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
|
||||
e.preventDefault();
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), activeCycle.id).catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
const addToFavoritePromise = addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), activeCycle.id);
|
||||
|
||||
setPromiseToast(addToFavoritePromise, {
|
||||
loading: "Adding cycle to favorites...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle added to favorites.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: "Couldn't add the cycle to favorites. Please try again.",
|
||||
});
|
||||
message: () => "Couldn't add the cycle to favorites. Please try again.",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -132,12 +136,22 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
|
||||
e.preventDefault();
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
removeCycleFromFavorites(workspaceSlug?.toString(), projectId.toString(), activeCycle.id).catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
const removeFromFavoritePromise = removeCycleFromFavorites(
|
||||
workspaceSlug?.toString(),
|
||||
projectId.toString(),
|
||||
activeCycle.id
|
||||
);
|
||||
|
||||
setPromiseToast(removeFromFavoritePromise, {
|
||||
loading: "Removing cycle from favorites...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle removed from favorites.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: "Couldn't add the cycle to favorites. Please try again.",
|
||||
});
|
||||
message: () => "Couldn't remove the cycle from favorites. Please try again.",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -4,11 +4,20 @@ import Link from "next/link";
|
||||
import { observer } from "mobx-react";
|
||||
// hooks
|
||||
import { useEventTracker, useCycle, useUser, useMember } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { CycleCreateUpdateModal, CycleDeleteModal } from "components/cycles";
|
||||
// ui
|
||||
import { Avatar, AvatarGroup, CustomMenu, Tooltip, LayersIcon, CycleGroupIcon } from "@plane/ui";
|
||||
import {
|
||||
Avatar,
|
||||
AvatarGroup,
|
||||
CustomMenu,
|
||||
Tooltip,
|
||||
LayersIcon,
|
||||
CycleGroupIcon,
|
||||
TOAST_TYPE,
|
||||
setToast,
|
||||
setPromiseToast,
|
||||
} from "@plane/ui";
|
||||
// icons
|
||||
import { Info, LinkIcon, Pencil, Star, Trash2 } from "lucide-react";
|
||||
// helpers
|
||||
@ -41,8 +50,6 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
|
||||
} = useUser();
|
||||
const { addCycleToFavorites, removeCycleFromFavorites, getCycleById } = useCycle();
|
||||
const { getUserDetails } = useMember();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// computed
|
||||
const cycleDetails = getCycleById(cycleId);
|
||||
|
||||
@ -81,8 +88,8 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
|
||||
const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
|
||||
|
||||
copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}`).then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link Copied!",
|
||||
message: "Cycle link copied to clipboard.",
|
||||
});
|
||||
@ -93,20 +100,26 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
|
||||
e.preventDefault();
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId)
|
||||
.then(() => {
|
||||
const addToFavoritePromise = addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId).then(
|
||||
() => {
|
||||
captureEvent(CYCLE_FAVORITED, {
|
||||
cycle_id: cycleId,
|
||||
element: "Grid layout",
|
||||
state: "SUCCESS",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
}
|
||||
);
|
||||
|
||||
setPromiseToast(addToFavoritePromise, {
|
||||
loading: "Adding cycle to favorites...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle added to favorites.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: "Couldn't add the cycle to favorites. Please try again.",
|
||||
});
|
||||
message: () => "Couldn't add the cycle to favorites. Please try again.",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -114,20 +127,28 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = observer((props) => {
|
||||
e.preventDefault();
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
removeCycleFromFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId)
|
||||
.then(() => {
|
||||
const removeFromFavoritePromise = removeCycleFromFavorites(
|
||||
workspaceSlug?.toString(),
|
||||
projectId.toString(),
|
||||
cycleId
|
||||
).then(() => {
|
||||
captureEvent(CYCLE_UNFAVORITED, {
|
||||
cycle_id: cycleId,
|
||||
element: "Grid layout",
|
||||
state: "SUCCESS",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: "Couldn't add the cycle to favorites. Please try again.",
|
||||
});
|
||||
|
||||
setPromiseToast(removeFromFavoritePromise, {
|
||||
loading: "Removing cycle from favorites...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle removed from favorites.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Couldn't remove the cycle from favorites. Please try again.",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -4,11 +4,20 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react";
|
||||
// hooks
|
||||
import { useEventTracker, useCycle, useUser, useMember } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { CycleCreateUpdateModal, CycleDeleteModal } from "components/cycles";
|
||||
// ui
|
||||
import { CustomMenu, Tooltip, CircularProgressIndicator, CycleGroupIcon, AvatarGroup, Avatar } from "@plane/ui";
|
||||
import {
|
||||
CustomMenu,
|
||||
Tooltip,
|
||||
CircularProgressIndicator,
|
||||
CycleGroupIcon,
|
||||
AvatarGroup,
|
||||
Avatar,
|
||||
TOAST_TYPE,
|
||||
setToast,
|
||||
setPromiseToast,
|
||||
} from "@plane/ui";
|
||||
// icons
|
||||
import { Check, Info, LinkIcon, Pencil, Star, Trash2, User2 } from "lucide-react";
|
||||
// helpers
|
||||
@ -45,8 +54,6 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
|
||||
} = useUser();
|
||||
const { getCycleById, addCycleToFavorites, removeCycleFromFavorites } = useCycle();
|
||||
const { getUserDetails } = useMember();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleCopyText = (e: MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
@ -54,8 +61,8 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
|
||||
const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
|
||||
|
||||
copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}`).then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link Copied!",
|
||||
message: "Cycle link copied to clipboard.",
|
||||
});
|
||||
@ -66,20 +73,26 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
|
||||
e.preventDefault();
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId)
|
||||
.then(() => {
|
||||
const addToFavoritePromise = addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId).then(
|
||||
() => {
|
||||
captureEvent(CYCLE_FAVORITED, {
|
||||
cycle_id: cycleId,
|
||||
element: "List layout",
|
||||
state: "SUCCESS",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
}
|
||||
);
|
||||
|
||||
setPromiseToast(addToFavoritePromise, {
|
||||
loading: "Adding cycle to favorites...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle added to favorites.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: "Couldn't add the cycle to favorites. Please try again.",
|
||||
});
|
||||
message: () => "Couldn't add the cycle to favorites. Please try again.",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -87,20 +100,28 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
|
||||
e.preventDefault();
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
removeCycleFromFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId)
|
||||
.then(() => {
|
||||
const removeFromFavoritePromise = removeCycleFromFavorites(
|
||||
workspaceSlug?.toString(),
|
||||
projectId.toString(),
|
||||
cycleId
|
||||
).then(() => {
|
||||
captureEvent(CYCLE_UNFAVORITED, {
|
||||
cycle_id: cycleId,
|
||||
element: "List layout",
|
||||
state: "SUCCESS",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: "Couldn't add the cycle to favorites. Please try again.",
|
||||
});
|
||||
|
||||
setPromiseToast(removeFromFavoritePromise, {
|
||||
loading: "Removing cycle from favorites...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle removed from favorites.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Couldn't remove the cycle from favorites. Please try again.",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -5,9 +5,8 @@ import { observer } from "mobx-react-lite";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
// hooks
|
||||
import { useEventTracker, useCycle } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { ICycle } from "@plane/types";
|
||||
// constants
|
||||
@ -31,8 +30,6 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
|
||||
// store hooks
|
||||
const { captureCycleEvent } = useEventTracker();
|
||||
const { deleteCycle } = useCycle();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const formSubmit = async () => {
|
||||
if (!cycle) return;
|
||||
@ -41,8 +38,8 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
|
||||
try {
|
||||
await deleteCycle(workspaceSlug, projectId, cycle.id)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Cycle deleted successfully.",
|
||||
});
|
||||
@ -62,8 +59,8 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
|
||||
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Warning!",
|
||||
message: "Something went wrong please try again later.",
|
||||
});
|
||||
|
@ -4,10 +4,11 @@ import { Dialog, Transition } from "@headlessui/react";
|
||||
import { CycleService } from "services/cycle.service";
|
||||
// hooks
|
||||
import { useEventTracker, useCycle, useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useLocalStorage from "hooks/use-local-storage";
|
||||
// components
|
||||
import { CycleForm } from "components/cycles";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import type { CycleDateCheckData, ICycle, TCycleView } from "@plane/types";
|
||||
// constants
|
||||
@ -32,8 +33,6 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
|
||||
const { captureCycleEvent } = useEventTracker();
|
||||
const { workspaceProjectIds } = useProject();
|
||||
const { createCycle, updateCycleDetails } = useCycle();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { setValue: setCycleTab } = useLocalStorage<TCycleView>("cycle_tab", "active");
|
||||
|
||||
@ -43,8 +42,8 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
|
||||
const selectedProjectId = payload.project_id ?? projectId.toString();
|
||||
await createCycle(workspaceSlug, selectedProjectId, payload)
|
||||
.then((res) => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Cycle created successfully.",
|
||||
});
|
||||
@ -54,8 +53,8 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err.detail ?? "Error in creating cycle. Please try again.",
|
||||
});
|
||||
@ -77,8 +76,8 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
|
||||
eventName: CYCLE_UPDATED,
|
||||
payload: { ...res, changed_properties: changed_properties, state: "SUCCESS" },
|
||||
});
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Cycle updated successfully.",
|
||||
});
|
||||
@ -88,8 +87,8 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
|
||||
eventName: CYCLE_UPDATED,
|
||||
payload: { ...payload, state: "FAILED" },
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err.detail ?? "Error in updating cycle. Please try again.",
|
||||
});
|
||||
@ -138,8 +137,8 @@ export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
|
||||
}
|
||||
handleClose();
|
||||
} else
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "You already have a cycle on the given dates, if you want to create a draft cycle, remove the dates.",
|
||||
});
|
||||
|
@ -8,13 +8,12 @@ import isEmpty from "lodash/isEmpty";
|
||||
import { CycleService } from "services/cycle.service";
|
||||
// hooks
|
||||
import { useEventTracker, useCycle, useUser, useMember } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { SidebarProgressStats } from "components/core";
|
||||
import ProgressChart from "components/core/sidebar/progress-chart";
|
||||
import { CycleDeleteModal } from "components/cycles/delete-modal";
|
||||
// ui
|
||||
import { Avatar, CustomMenu, Loader, LayersIcon } from "@plane/ui";
|
||||
import { Avatar, CustomMenu, Loader, LayersIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { ChevronDown, LinkIcon, Trash2, UserCircle2, AlertCircle, ChevronRight, CalendarClock } from "lucide-react";
|
||||
// helpers
|
||||
@ -60,8 +59,6 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
// derived values
|
||||
const cycleDetails = getCycleById(cycleId);
|
||||
const cycleOwnerDetails = cycleDetails ? getUserDetails(cycleDetails.owned_by_id) : undefined;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// form info
|
||||
const { control, reset } = useForm({
|
||||
defaultValues,
|
||||
@ -98,15 +95,15 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
const handleCopyText = () => {
|
||||
copyUrlToClipboard(`${workspaceSlug}/projects/${projectId}/cycles/${cycleId}`)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link Copied!",
|
||||
message: "Cycle link copied to clipboard.",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Some error occurred",
|
||||
});
|
||||
});
|
||||
@ -147,14 +144,14 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
|
||||
if (isDateValid) {
|
||||
submitChanges(payload, "date_range");
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Cycle updated successfully.",
|
||||
});
|
||||
} else {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message:
|
||||
"You already have a cycle on the given dates, if you want to create a draft cycle, you can do that by removing both the dates.",
|
||||
|
@ -3,10 +3,10 @@ import { useRouter } from "next/router";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useCycle, useIssues } from "hooks/store";
|
||||
// ui
|
||||
import { ContrastIcon, TransferIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
//icons
|
||||
import { ContrastIcon, TransferIcon } from "@plane/ui";
|
||||
import { AlertCircle, Search, X } from "lucide-react";
|
||||
// constants
|
||||
import { EIssuesStoreType } from "constants/issue";
|
||||
@ -30,23 +30,21 @@ export const TransferIssuesModal: React.FC<Props> = observer((props) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const transferIssue = async (payload: any) => {
|
||||
if (!workspaceSlug || !projectId || !cycleId) return;
|
||||
|
||||
// TODO: import transferIssuesFromCycle from store
|
||||
await transferIssuesFromCycle(workspaceSlug.toString(), projectId.toString(), cycleId.toString(), payload)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Issues transferred successfully",
|
||||
message: "Issues have been transferred successfully",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issues cannot be transfer. Please try again.",
|
||||
});
|
||||
|
@ -5,9 +5,8 @@ import { Dialog, Transition } from "@headlessui/react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// store hooks
|
||||
import { useEstimate } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, Input, TextArea } from "@plane/ui";
|
||||
import { Button, Input, TextArea, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { checkDuplicates } from "helpers/array.helper";
|
||||
// types
|
||||
@ -40,8 +39,6 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
||||
// store hooks
|
||||
const { createEstimate, updateEstimate } = useEstimate();
|
||||
// form info
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
formState: { errors, isSubmitting },
|
||||
handleSubmit,
|
||||
@ -67,8 +64,8 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
||||
const error = err?.error;
|
||||
const errorString = Array.isArray(error) ? error[0] : error;
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message:
|
||||
errorString ?? err.status === 400
|
||||
@ -89,8 +86,8 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
||||
const error = err?.error;
|
||||
const errorString = Array.isArray(error) ? error[0] : error;
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: errorString ?? "Estimate could not be updated. Please try again.",
|
||||
});
|
||||
@ -99,8 +96,8 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
||||
|
||||
const onSubmit = async (formData: FormValues) => {
|
||||
if (!formData.name || formData.name === "") {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Estimate title cannot be empty.",
|
||||
});
|
||||
@ -115,8 +112,8 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
||||
formData.value5 === "" ||
|
||||
formData.value6 === ""
|
||||
) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Estimate point cannot be empty.",
|
||||
});
|
||||
@ -131,8 +128,8 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
||||
formData.value5.length > 20 ||
|
||||
formData.value6.length > 20
|
||||
) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Estimate point cannot have more than 20 characters.",
|
||||
});
|
||||
@ -149,8 +146,8 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
||||
formData.value6,
|
||||
])
|
||||
) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Estimate points cannot have duplicate values.",
|
||||
});
|
||||
|
@ -5,11 +5,10 @@ import { observer } from "mobx-react-lite";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
// store hooks
|
||||
import { useEstimate } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// types
|
||||
import { IEstimate } from "@plane/types";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -26,8 +25,6 @@ export const DeleteEstimateModal: React.FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
// store hooks
|
||||
const { deleteEstimate } = useEstimate();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleEstimateDelete = () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
@ -43,8 +40,8 @@ export const DeleteEstimateModal: React.FC<Props> = observer((props) => {
|
||||
const error = err?.error;
|
||||
const errorString = Array.isArray(error) ? error[0] : error;
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: errorString ?? "Estimate could not be deleted. Please try again",
|
||||
});
|
||||
|
@ -3,9 +3,8 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, CustomMenu } from "@plane/ui";
|
||||
import { Button, CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
//icons
|
||||
import { Pencil, Trash2 } from "lucide-react";
|
||||
// helpers
|
||||
@ -26,8 +25,6 @@ export const EstimateListItem: React.FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
// store hooks
|
||||
const { currentProjectDetails, updateProject } = useProject();
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleUseEstimate = async () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
@ -38,8 +35,8 @@ export const EstimateListItem: React.FC<Props> = observer((props) => {
|
||||
const error = err?.error;
|
||||
const errorString = Array.isArray(error) ? error[0] : error;
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: errorString ?? "Estimate points could not be used. Please try again.",
|
||||
});
|
||||
|
@ -4,12 +4,11 @@ import { observer } from "mobx-react-lite";
|
||||
import { useTheme } from "next-themes";
|
||||
// store hooks
|
||||
import { useEstimate, useProject, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { CreateUpdateEstimateModal, DeleteEstimateModal, EstimateListItem } from "components/estimates";
|
||||
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
||||
// ui
|
||||
import { Button, Loader } from "@plane/ui";
|
||||
import { Button, Loader, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IEstimate } from "@plane/types";
|
||||
// helpers
|
||||
@ -31,8 +30,6 @@ export const EstimatesList: React.FC = observer(() => {
|
||||
const { updateProject, currentProjectDetails } = useProject();
|
||||
const { projectEstimates, getProjectEstimateById } = useEstimate();
|
||||
const { currentUser } = useUser();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const editEstimate = (estimate: IEstimate) => {
|
||||
setEstimateFormOpen(true);
|
||||
@ -50,8 +47,8 @@ export const EstimatesList: React.FC = observer(() => {
|
||||
const error = err?.error;
|
||||
const errorString = Array.isArray(error) ? error[0] : error;
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: errorString ?? "Estimate could not be disabled. Please try again",
|
||||
});
|
||||
|
@ -6,10 +6,8 @@ import { Dialog, Transition } from "@headlessui/react";
|
||||
import { useProject } from "hooks/store";
|
||||
// services
|
||||
import { ProjectExportService } from "services/project";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, CustomSearchSelect } from "@plane/ui";
|
||||
import { Button, CustomSearchSelect, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IUser, IImporterService } from "@plane/types";
|
||||
|
||||
@ -34,8 +32,6 @@ export const Exporter: React.FC<Props> = observer((props) => {
|
||||
const { workspaceSlug } = router.query;
|
||||
// store hooks
|
||||
const { workspaceProjectIds, getProjectById } = useProject();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const options = workspaceProjectIds?.map((projectId) => {
|
||||
const projectDetails = getProjectById(projectId);
|
||||
@ -71,8 +67,8 @@ export const Exporter: React.FC<Props> = observer((props) => {
|
||||
mutateServices();
|
||||
router.push(`/${workspaceSlug}/settings/exports`);
|
||||
setExportLoading(false);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Export Successful",
|
||||
message: `You will be able to download the exported ${
|
||||
provider === "csv" ? "CSV" : provider === "xlsx" ? "Excel" : provider === "json" ? "JSON" : ""
|
||||
@ -81,8 +77,8 @@ export const Exporter: React.FC<Props> = observer((props) => {
|
||||
})
|
||||
.catch(() => {
|
||||
setExportLoading(false);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Export was unsuccessful. Please try again.",
|
||||
});
|
||||
|
@ -5,7 +5,6 @@ import { DayPicker } from "react-day-picker";
|
||||
import { Popover } from "@headlessui/react";
|
||||
// hooks
|
||||
import { useUser, useInboxIssues, useIssueDetail, useWorkspace, useEventTracker } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import {
|
||||
AcceptIssueModal,
|
||||
@ -14,7 +13,7 @@ import {
|
||||
SelectDuplicateInboxIssueModal,
|
||||
} from "components/inbox";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { CheckCircle2, ChevronDown, ChevronUp, Clock, FileStack, Trash2, XCircle } from "lucide-react";
|
||||
// types
|
||||
@ -51,7 +50,6 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
||||
currentUser,
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// states
|
||||
const [date, setDate] = useState(new Date());
|
||||
@ -74,8 +72,8 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
||||
if (!workspaceSlug || !projectId || !inboxId || !inboxIssueId) throw new Error("Missing required parameters");
|
||||
await updateInboxIssueStatus(workspaceSlug, projectId, inboxId, inboxIssueId, data);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Something went wrong while updating inbox status. Please try again.",
|
||||
});
|
||||
@ -98,8 +96,8 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
||||
pathname: `/${workspaceSlug}/projects/${projectId}/inbox/${inboxId}`,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Something went wrong while deleting inbox issue. Please try again.",
|
||||
});
|
||||
@ -122,7 +120,6 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
||||
inboxIssueId,
|
||||
updateInboxIssueStatus,
|
||||
removeInboxIssue,
|
||||
setToastAlert,
|
||||
captureIssueEvent,
|
||||
router,
|
||||
]
|
||||
|
@ -7,7 +7,6 @@ import { RichTextEditorWithRef } from "@plane/rich-text-editor";
|
||||
import { Sparkle } from "lucide-react";
|
||||
// hooks
|
||||
import { useApplication, useEventTracker, useWorkspace, useInboxIssues, useMention } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
import { AIService } from "services/ai.service";
|
||||
@ -15,7 +14,7 @@ import { AIService } from "services/ai.service";
|
||||
import { PriorityDropdown } from "components/dropdowns";
|
||||
import { GptAssistantPopover } from "components/core";
|
||||
// ui
|
||||
import { Button, Input, ToggleSwitch } from "@plane/ui";
|
||||
import { Button, Input, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
// constants
|
||||
@ -46,9 +45,6 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false);
|
||||
// refs
|
||||
const editorRef = useRef<any>(null);
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, inboxId } = router.query as {
|
||||
@ -56,6 +52,8 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
projectId: string;
|
||||
inboxId: string;
|
||||
};
|
||||
// hooks
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
const workspaceStore = useWorkspace();
|
||||
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string;
|
||||
|
||||
@ -138,8 +136,8 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.response === "")
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message:
|
||||
"Issue title isn't informative enough to generate the description. Please try with a different title.",
|
||||
@ -150,14 +148,14 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
||||
const error = err?.data?.error;
|
||||
|
||||
if (err.status === 429)
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: error || "You have reached the maximum number of requests of 50 requests per month per user.",
|
||||
});
|
||||
else
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: error || "Some error occurred. Please try again.",
|
||||
});
|
||||
|
@ -2,13 +2,10 @@ import React, { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
import { Combobox, Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// services
|
||||
import { IssueService } from "services/issue";
|
||||
// ui
|
||||
import { Button, LayersIcon } from "@plane/ui";
|
||||
import { Button, LayersIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { Search } from "lucide-react";
|
||||
// fetch-keys
|
||||
@ -30,8 +27,6 @@ export const SelectDuplicateInboxIssueModal: React.FC<Props> = (props) => {
|
||||
const [query, setQuery] = useState("");
|
||||
const [selectedItem, setSelectedItem] = useState<string>("");
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
@ -62,9 +57,9 @@ export const SelectDuplicateInboxIssueModal: React.FC<Props> = (props) => {
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!selectedItem || selectedItem.length === 0)
|
||||
return setToastAlert({
|
||||
return setToast({
|
||||
title: "Error",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
});
|
||||
onSubmit(selectedItem);
|
||||
handleClose();
|
||||
|
@ -2,12 +2,11 @@ import { FC, useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Eye, EyeOff } from "lucide-react";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IFormattedInstanceConfiguration } from "@plane/types";
|
||||
// hooks
|
||||
import { useApplication } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
export interface IInstanceAIForm {
|
||||
config: IFormattedInstanceConfiguration;
|
||||
@ -24,8 +23,6 @@ export const InstanceAIForm: FC<IInstanceAIForm> = (props) => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// store
|
||||
const { instance: instanceStore } = useApplication();
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
// form data
|
||||
const {
|
||||
handleSubmit,
|
||||
@ -44,9 +41,9 @@ export const InstanceAIForm: FC<IInstanceAIForm> = (props) => {
|
||||
await instanceStore
|
||||
.updateInstanceConfigurations(payload)
|
||||
.then(() =>
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Success",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "AI Settings updated successfully",
|
||||
})
|
||||
)
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { FC, useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// ui
|
||||
import { Button, Input, ToggleSwitch } from "@plane/ui";
|
||||
import { Button, Input, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
import { Eye, EyeOff } from "lucide-react";
|
||||
// types
|
||||
import { IFormattedInstanceConfiguration } from "@plane/types";
|
||||
// hooks
|
||||
import { useApplication } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
export interface IInstanceEmailForm {
|
||||
config: IFormattedInstanceConfiguration;
|
||||
@ -29,8 +28,6 @@ export const InstanceEmailForm: FC<IInstanceEmailForm> = (props) => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// store hooks
|
||||
const { instance: instanceStore } = useApplication();
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
// form data
|
||||
const {
|
||||
handleSubmit,
|
||||
@ -55,9 +52,9 @@ export const InstanceEmailForm: FC<IInstanceEmailForm> = (props) => {
|
||||
await instanceStore
|
||||
.updateInstanceConfigurations(payload)
|
||||
.then(() =>
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Success",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Email Settings updated successfully",
|
||||
})
|
||||
)
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { FC } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IInstance, IInstanceAdmin } from "@plane/types";
|
||||
// hooks
|
||||
import { useApplication } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
export interface IInstanceGeneralForm {
|
||||
instance: IInstance;
|
||||
@ -22,8 +21,6 @@ export const InstanceGeneralForm: FC<IInstanceGeneralForm> = (props) => {
|
||||
const { instance, instanceAdmins } = props;
|
||||
// store hooks
|
||||
const { instance: instanceStore } = useApplication();
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
// form data
|
||||
const {
|
||||
handleSubmit,
|
||||
@ -42,9 +39,9 @@ export const InstanceGeneralForm: FC<IInstanceGeneralForm> = (props) => {
|
||||
await instanceStore
|
||||
.updateInstanceInfo(payload)
|
||||
.then(() =>
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Success",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Settings updated successfully",
|
||||
})
|
||||
)
|
||||
|
@ -2,12 +2,11 @@ import { FC, useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Copy, Eye, EyeOff } from "lucide-react";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IFormattedInstanceConfiguration } from "@plane/types";
|
||||
// hooks
|
||||
import { useApplication } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
export interface IInstanceGithubConfigForm {
|
||||
config: IFormattedInstanceConfiguration;
|
||||
@ -24,8 +23,6 @@ export const InstanceGithubConfigForm: FC<IInstanceGithubConfigForm> = (props) =
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// store hooks
|
||||
const { instance: instanceStore } = useApplication();
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
// form data
|
||||
const {
|
||||
handleSubmit,
|
||||
@ -44,9 +41,9 @@ export const InstanceGithubConfigForm: FC<IInstanceGithubConfigForm> = (props) =
|
||||
await instanceStore
|
||||
.updateInstanceConfigurations(payload)
|
||||
.then(() =>
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Success",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Github Configuration Settings updated successfully",
|
||||
})
|
||||
)
|
||||
@ -145,9 +142,9 @@ export const InstanceGithubConfigForm: FC<IInstanceGithubConfigForm> = (props) =
|
||||
className="flex items-center justify-between py-2"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(originURL);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The Origin URL has been successfully copied to your clipboard",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Copied to clipboard",
|
||||
});
|
||||
}}
|
||||
|
@ -2,12 +2,11 @@ import { FC } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Copy } from "lucide-react";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IFormattedInstanceConfiguration } from "@plane/types";
|
||||
// hooks
|
||||
import { useApplication } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
export interface IInstanceGoogleConfigForm {
|
||||
config: IFormattedInstanceConfiguration;
|
||||
@ -22,8 +21,6 @@ export const InstanceGoogleConfigForm: FC<IInstanceGoogleConfigForm> = (props) =
|
||||
const { config } = props;
|
||||
// store hooks
|
||||
const { instance: instanceStore } = useApplication();
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
// form data
|
||||
const {
|
||||
handleSubmit,
|
||||
@ -42,9 +39,9 @@ export const InstanceGoogleConfigForm: FC<IInstanceGoogleConfigForm> = (props) =
|
||||
await instanceStore
|
||||
.updateInstanceConfigurations(payload)
|
||||
.then(() =>
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Success",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Google Configuration Settings updated successfully",
|
||||
})
|
||||
)
|
||||
@ -94,9 +91,9 @@ export const InstanceGoogleConfigForm: FC<IInstanceGoogleConfigForm> = (props) =
|
||||
className="flex items-center justify-between py-2"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(originURL);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The Origin URL has been successfully copied to your clipboard",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Copied to clipboard",
|
||||
});
|
||||
}}
|
||||
|
@ -2,12 +2,11 @@ import { FC, useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Eye, EyeOff } from "lucide-react";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IFormattedInstanceConfiguration } from "@plane/types";
|
||||
// hooks
|
||||
import { useApplication } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
export interface IInstanceImageConfigForm {
|
||||
config: IFormattedInstanceConfiguration;
|
||||
@ -23,8 +22,6 @@ export const InstanceImageConfigForm: FC<IInstanceImageConfigForm> = (props) =>
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
// store hooks
|
||||
const { instance: instanceStore } = useApplication();
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
// form data
|
||||
const {
|
||||
handleSubmit,
|
||||
@ -42,9 +39,9 @@ export const InstanceImageConfigForm: FC<IInstanceImageConfigForm> = (props) =>
|
||||
await instanceStore
|
||||
.updateInstanceConfigurations(payload)
|
||||
.then(() =>
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Success",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Image Configuration Settings updated successfully",
|
||||
})
|
||||
)
|
||||
|
@ -4,12 +4,10 @@ import { Eye, EyeOff, XCircle } from "lucide-react";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
// ui
|
||||
import { Input, Button } from "@plane/ui";
|
||||
import { Input, Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// services
|
||||
import { AuthService } from "services/auth.service";
|
||||
const authService = new AuthService();
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// helpers
|
||||
import { checkEmailValidity } from "helpers/string.helper";
|
||||
|
||||
@ -40,8 +38,6 @@ export const InstanceSetupSignInForm: FC<IInstanceSetupEmailForm> = (props) => {
|
||||
password: "",
|
||||
},
|
||||
});
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleFormSubmit = async (formValues: InstanceSetupEmailFormValues) => {
|
||||
const payload = {
|
||||
@ -56,8 +52,8 @@ export const InstanceSetupSignInForm: FC<IInstanceSetupEmailForm> = (props) => {
|
||||
handleNextStep(formValues.email);
|
||||
})
|
||||
.catch((err) => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: err?.error ?? "Something went wrong. Please try again.",
|
||||
});
|
||||
|
@ -10,10 +10,8 @@ import { Menu, Transition } from "@headlessui/react";
|
||||
import { LogIn, LogOut, Settings, UserCog2 } from "lucide-react";
|
||||
// hooks
|
||||
import { useApplication, useUser } from "hooks/store";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Avatar, Tooltip } from "@plane/ui";
|
||||
import { Avatar, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
|
||||
// Static Data
|
||||
const PROFILE_LINKS = [
|
||||
@ -35,7 +33,6 @@ export const InstanceSidebarDropdown = observer(() => {
|
||||
} = useApplication();
|
||||
const { signOut, currentUser, currentUserSettings } = useUser();
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
// redirect url for normal mode
|
||||
@ -53,8 +50,8 @@ export const InstanceSidebarDropdown = observer(() => {
|
||||
router.push("/");
|
||||
})
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Failed to sign out. Please try again.",
|
||||
})
|
||||
|
@ -8,10 +8,8 @@ import { mutate } from "swr";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import { IntegrationService } from "services/integrations/integration.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
// types
|
||||
@ -36,8 +34,6 @@ export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data }
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleDeletion = () => {
|
||||
if (!workspaceSlug || !data) return;
|
||||
|
||||
@ -52,8 +48,8 @@ export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data }
|
||||
integrationService
|
||||
.deleteImporterService(workspaceSlug as string, data.service, data.id)
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Something went wrong. Please try again.",
|
||||
})
|
||||
|
@ -10,8 +10,6 @@ import useSWR, { mutate } from "swr";
|
||||
import { useForm } from "react-hook-form";
|
||||
// services
|
||||
import { IntegrationService, GithubIntegrationService } from "services/integrations";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import {
|
||||
GithubImportConfigure,
|
||||
@ -21,7 +19,7 @@ import {
|
||||
GithubImportConfirm,
|
||||
} from "components/integration";
|
||||
// icons
|
||||
import { UserGroupIcon } from "@plane/ui";
|
||||
import { UserGroupIcon, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
import { ArrowLeft, Check, List, Settings, UploadCloud } from "lucide-react";
|
||||
// images
|
||||
import GithubLogo from "public/services/github.png";
|
||||
@ -92,8 +90,6 @@ export const GithubImporterRoot: React.FC = () => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, provider } = router.query;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { handleSubmit, control, setValue, watch } = useForm<TFormValues>({
|
||||
defaultValues: defaultFormValues,
|
||||
});
|
||||
@ -149,8 +145,8 @@ export const GithubImporterRoot: React.FC = () => {
|
||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
|
||||
})
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Import was unsuccessful. Please try again.",
|
||||
})
|
||||
|
@ -8,10 +8,9 @@ import useSWR, { mutate } from "swr";
|
||||
import { IntegrationService } from "services/integrations";
|
||||
// hooks
|
||||
import { useApplication, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useIntegrationPopup from "hooks/use-integration-popup";
|
||||
// ui
|
||||
import { Button, Loader, Tooltip } from "@plane/ui";
|
||||
import { Button, Loader, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import GithubLogo from "public/services/github.png";
|
||||
import SlackLogo from "public/services/slack.png";
|
||||
@ -54,8 +53,6 @@ export const SingleIntegrationCard: React.FC<Props> = observer(({ integration })
|
||||
const {
|
||||
membership: { currentWorkspaceRole },
|
||||
} = useUser();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const isUserAdmin = currentWorkspaceRole === 20;
|
||||
|
||||
@ -87,8 +84,8 @@ export const SingleIntegrationCard: React.FC<Props> = observer(({ integration })
|
||||
);
|
||||
setDeletingIntegration(false);
|
||||
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Deleted successfully!",
|
||||
message: `${integration.title} integration deleted successfully.`,
|
||||
});
|
||||
@ -96,8 +93,8 @@ export const SingleIntegrationCard: React.FC<Props> = observer(({ integration })
|
||||
.catch(() => {
|
||||
setDeletingIntegration(false);
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: `${integration.title} integration could not be deleted. Please try again.`,
|
||||
});
|
||||
|
@ -3,9 +3,8 @@ import { Dialog, Transition } from "@headlessui/react";
|
||||
// hooks
|
||||
import { useProject } from "hooks/store";
|
||||
import { useIssues } from "hooks/store/use-issues";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
|
||||
@ -24,8 +23,6 @@ export const ArchiveIssueModal: React.FC<Props> = (props) => {
|
||||
// store hooks
|
||||
const { getProjectById } = useProject();
|
||||
const { issueMap } = useIssues();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
if (!dataId && !data) return null;
|
||||
|
||||
@ -44,8 +41,8 @@ export const ArchiveIssueModal: React.FC<Props> = (props) => {
|
||||
await onSubmit()
|
||||
.then(() => onClose())
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issue could not be archived. Please try again.",
|
||||
})
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { FC, useMemo } from "react";
|
||||
// hooks
|
||||
import { useEventTracker, useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { IssueAttachmentUpload } from "./attachment-upload";
|
||||
import { IssueAttachmentsList } from "./attachments-list";
|
||||
@ -24,19 +25,27 @@ export const IssueAttachmentRoot: FC<TIssueAttachmentRoot> = (props) => {
|
||||
// hooks
|
||||
const { createAttachment, removeAttachment } = useIssueDetail();
|
||||
const { captureIssueEvent } = useEventTracker();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleAttachmentOperations: TAttachmentOperations = useMemo(
|
||||
() => ({
|
||||
create: async (data: FormData) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing required fields");
|
||||
const res = await createAttachment(workspaceSlug, projectId, issueId, data);
|
||||
setToastAlert({
|
||||
message: "The attachment has been successfully uploaded",
|
||||
type: "success",
|
||||
|
||||
const attachmentUploadPromise = createAttachment(workspaceSlug, projectId, issueId, data);
|
||||
setPromiseToast(attachmentUploadPromise, {
|
||||
loading: "Uploading attachment...",
|
||||
success: {
|
||||
title: "Attachment uploaded",
|
||||
message: () => "The attachment has been successfully uploaded",
|
||||
},
|
||||
error: {
|
||||
title: "Attachment not uploaded",
|
||||
message: () => "The attachment could not be uploaded",
|
||||
},
|
||||
});
|
||||
|
||||
const res = await attachmentUploadPromise;
|
||||
captureIssueEvent({
|
||||
eventName: "Issue attachment added",
|
||||
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
|
||||
@ -50,20 +59,15 @@ export const IssueAttachmentRoot: FC<TIssueAttachmentRoot> = (props) => {
|
||||
eventName: "Issue attachment added",
|
||||
payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
|
||||
});
|
||||
setToastAlert({
|
||||
message: "The attachment could not be uploaded",
|
||||
type: "error",
|
||||
title: "Attachment not uploaded",
|
||||
});
|
||||
}
|
||||
},
|
||||
remove: async (attachmentId: string) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing required fields");
|
||||
await removeAttachment(workspaceSlug, projectId, issueId, attachmentId);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The attachment has been successfully removed",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Attachment removed",
|
||||
});
|
||||
captureIssueEvent({
|
||||
@ -83,15 +87,15 @@ export const IssueAttachmentRoot: FC<TIssueAttachmentRoot> = (props) => {
|
||||
change_details: "",
|
||||
},
|
||||
});
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The Attachment could not be removed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Attachment not removed",
|
||||
});
|
||||
}
|
||||
},
|
||||
}),
|
||||
[workspaceSlug, projectId, issueId, createAttachment, removeAttachment, setToastAlert]
|
||||
[workspaceSlug, projectId, issueId, createAttachment, removeAttachment]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -2,9 +2,7 @@ import { useEffect, useState, Fragment } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { useIssues } from "hooks/store/use-issues";
|
||||
import { TIssue } from "@plane/types";
|
||||
@ -25,7 +23,6 @@ export const DeleteIssueModal: React.FC<Props> = (props) => {
|
||||
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
// hooks
|
||||
const { getProjectById } = useProject();
|
||||
|
||||
@ -50,9 +47,9 @@ export const DeleteIssueModal: React.FC<Props> = (props) => {
|
||||
onClose();
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Error",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Failed to delete issue",
|
||||
});
|
||||
})
|
||||
|
@ -71,16 +71,10 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = observer((props) => {
|
||||
async (formData: Partial<TIssue>) => {
|
||||
if (!formData?.name || formData?.name.length === 0 || formData?.name.length > 255) return;
|
||||
|
||||
await issueOperations.update(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
{
|
||||
await issueOperations.update(workspaceSlug, projectId, issueId, {
|
||||
name: formData.name ?? "",
|
||||
description_html: formData.description_html ?? "<p></p>",
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
},
|
||||
[workspaceSlug, projectId, issueId, issueOperations]
|
||||
);
|
||||
|
@ -41,9 +41,7 @@ export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = (props) =>
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedValue && debouncedValue !== value) {
|
||||
issueOperations
|
||||
.update(workspaceSlug, projectId, issueId, { description_html: debouncedValue }, false)
|
||||
.finally(() => {
|
||||
issueOperations.update(workspaceSlug, projectId, issueId, { description_html: debouncedValue }).finally(() => {
|
||||
setIsSubmitting("submitted");
|
||||
});
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ export const IssueCycleSelect: React.FC<TIssueCycleSelect> = observer((props) =>
|
||||
dropdownArrow
|
||||
dropdownArrowClassName="h-3.5 w-3.5 hidden group-hover:inline"
|
||||
/>
|
||||
{isUpdating && <Spinner className="h-4 w-4" />}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -6,7 +6,8 @@ import { InboxIssueMainContent } from "./main-content";
|
||||
import { InboxIssueDetailsSidebar } from "./sidebar";
|
||||
// hooks
|
||||
import { useEventTracker, useInboxIssues, useIssueDetail, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
import { TIssueOperations } from "../root";
|
||||
@ -34,7 +35,6 @@ export const InboxIssueDetailRoot: FC<TInboxIssueDetailRoot> = (props) => {
|
||||
fetchComments,
|
||||
} = useIssueDetail();
|
||||
const { captureIssueEvent } = useEventTracker();
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
@ -53,17 +53,9 @@ export const InboxIssueDetailRoot: FC<TInboxIssueDetailRoot> = (props) => {
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
showToast: boolean = true
|
||||
) => {
|
||||
try {
|
||||
await updateInboxIssue(workspaceSlug, projectId, inboxId, issueId, data);
|
||||
if (showToast) {
|
||||
setToastAlert({
|
||||
title: "Issue updated successfully",
|
||||
type: "success",
|
||||
message: "Issue updated successfully",
|
||||
});
|
||||
}
|
||||
captureIssueEvent({
|
||||
eventName: "Inbox issue updated",
|
||||
payload: { ...data, state: "SUCCESS", element: "Inbox" },
|
||||
@ -74,9 +66,9 @@ export const InboxIssueDetailRoot: FC<TInboxIssueDetailRoot> = (props) => {
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue update failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Issue update failed",
|
||||
});
|
||||
captureIssueEvent({
|
||||
@ -93,9 +85,9 @@ export const InboxIssueDetailRoot: FC<TInboxIssueDetailRoot> = (props) => {
|
||||
remove: async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
await removeInboxIssue(workspaceSlug, projectId, inboxId, issueId);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue deleted successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Issue deleted successfully",
|
||||
});
|
||||
captureIssueEvent({
|
||||
@ -109,15 +101,15 @@ export const InboxIssueDetailRoot: FC<TInboxIssueDetailRoot> = (props) => {
|
||||
payload: { id: issueId, state: "FAILED", element: "Inbox" },
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue delete failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Issue delete failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
}),
|
||||
[inboxId, fetchInboxIssueById, updateInboxIssue, removeInboxIssue, setToastAlert]
|
||||
[inboxId, fetchInboxIssueById, updateInboxIssue, removeInboxIssue]
|
||||
);
|
||||
|
||||
useSWR(
|
||||
|
@ -3,7 +3,8 @@ import { observer } from "mobx-react-lite";
|
||||
import { History, LucideIcon, MessageCircle, ListRestart } from "lucide-react";
|
||||
// hooks
|
||||
import { useIssueDetail, useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { IssueActivityCommentRoot, IssueActivityRoot, IssueCommentRoot, IssueCommentCreate } from "./";
|
||||
// types
|
||||
@ -45,7 +46,6 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
|
||||
const { workspaceSlug, projectId, issueId } = props;
|
||||
// hooks
|
||||
const { createComment, updateComment, removeComment } = useIssueDetail();
|
||||
const { setToastAlert } = useToast();
|
||||
const { getProjectById } = useProject();
|
||||
// state
|
||||
const [activityTab, setActivityTab] = useState<TActivityTabs>("all");
|
||||
@ -56,15 +56,15 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing fields");
|
||||
await createComment(workspaceSlug, projectId, issueId, data);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Comment created successfully.",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Comment created successfully.",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Comment creation failed.",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Comment creation failed. Please try again later.",
|
||||
});
|
||||
}
|
||||
@ -73,15 +73,15 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing fields");
|
||||
await updateComment(workspaceSlug, projectId, issueId, commentId, data);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Comment updated successfully.",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Comment updated successfully.",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Comment update failed.",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Comment update failed. Please try again later.",
|
||||
});
|
||||
}
|
||||
@ -90,21 +90,21 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing fields");
|
||||
await removeComment(workspaceSlug, projectId, issueId, commentId);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Comment removed successfully.",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Comment removed successfully.",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Comment remove failed.",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Comment remove failed. Please try again later.",
|
||||
});
|
||||
}
|
||||
},
|
||||
}),
|
||||
[workspaceSlug, projectId, issueId, createComment, updateComment, removeComment, setToastAlert]
|
||||
[workspaceSlug, projectId, issueId, createComment, updateComment, removeComment]
|
||||
);
|
||||
|
||||
const project = getProjectById(projectId);
|
||||
|
@ -5,9 +5,8 @@ import { TwitterPicker } from "react-color";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
// hooks
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Input } from "@plane/ui";
|
||||
import { Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TLabelOperations } from "./root";
|
||||
import { IIssueLabel } from "@plane/types";
|
||||
@ -28,7 +27,6 @@ const defaultValues: Partial<IIssueLabel> = {
|
||||
export const LabelCreate: FC<ILabelCreate> = (props) => {
|
||||
const { workspaceSlug, projectId, issueId, labelOperations, disabled = false } = props;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
issue: { getIssueById },
|
||||
} = useIssueDetail();
|
||||
@ -63,9 +61,9 @@ export const LabelCreate: FC<ILabelCreate> = (props) => {
|
||||
await labelOperations.updateIssue(workspaceSlug, projectId, issueId, { label_ids: currentLabels });
|
||||
reset(defaultValues);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Label creation failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Label creation failed. Please try again sometime later.",
|
||||
});
|
||||
}
|
||||
|
@ -4,9 +4,10 @@ import { observer } from "mobx-react-lite";
|
||||
import { LabelList, LabelCreate, IssueLabelSelectRoot } from "./";
|
||||
// hooks
|
||||
import { useIssueDetail, useLabel } from "hooks/store";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IIssueLabel, TIssue } from "@plane/types";
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
export type TIssueLabel = {
|
||||
workspaceSlug: string;
|
||||
@ -27,7 +28,6 @@ export const IssueLabel: FC<TIssueLabel> = observer((props) => {
|
||||
// hooks
|
||||
const { updateIssue } = useIssueDetail();
|
||||
const { createLabel } = useLabel();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const labelOperations: TLabelOperations = useMemo(
|
||||
() => ({
|
||||
@ -35,16 +35,10 @@ export const IssueLabel: FC<TIssueLabel> = observer((props) => {
|
||||
try {
|
||||
if (onLabelUpdate) onLabelUpdate(data.label_ids || []);
|
||||
else await updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
if (!isInboxIssue)
|
||||
setToastAlert({
|
||||
title: "Issue updated successfully",
|
||||
type: "success",
|
||||
message: "Issue updated successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue update failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Issue update failed",
|
||||
});
|
||||
}
|
||||
@ -53,23 +47,23 @@ export const IssueLabel: FC<TIssueLabel> = observer((props) => {
|
||||
try {
|
||||
const labelResponse = await createLabel(workspaceSlug, projectId, data);
|
||||
if (!isInboxIssue)
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Label created successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Label created successfully",
|
||||
});
|
||||
return labelResponse;
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Label creation failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Label creation failed",
|
||||
});
|
||||
return error;
|
||||
}
|
||||
},
|
||||
}),
|
||||
[updateIssue, createLabel, setToastAlert, onLabelUpdate]
|
||||
[updateIssue, createLabel, onLabelUpdate]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { FC, useState } from "react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useIssueDetail, useMember } from "hooks/store";
|
||||
// ui
|
||||
import { ExternalLinkIcon, Tooltip } from "@plane/ui";
|
||||
import { ExternalLinkIcon, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { Pencil, Trash2, LinkIcon } from "lucide-react";
|
||||
// types
|
||||
@ -27,7 +26,6 @@ export const IssueLinkDetail: FC<TIssueLinkDetail> = (props) => {
|
||||
link: { getLinkById },
|
||||
} = useIssueDetail();
|
||||
const { getUserDetails } = useMember();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// state
|
||||
const [isIssueLinkModalOpen, setIsIssueLinkModalOpen] = useState(false);
|
||||
@ -55,8 +53,8 @@ export const IssueLinkDetail: FC<TIssueLinkDetail> = (props) => {
|
||||
className="flex w-full items-start justify-between gap-2 cursor-pointer"
|
||||
onClick={() => {
|
||||
copyTextToClipboard(linkDetail.url);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link copied!",
|
||||
message: "Link copied to clipboard",
|
||||
});
|
||||
|
@ -2,7 +2,8 @@ import { FC, useCallback, useMemo, useState } from "react";
|
||||
import { Plus } from "lucide-react";
|
||||
// hooks
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { IssueLinkCreateUpdateModal } from "./create-update-link-modal";
|
||||
import { IssueLinkList } from "./links";
|
||||
@ -37,24 +38,22 @@ export const IssueLinkRoot: FC<TIssueLinkRoot> = (props) => {
|
||||
[toggleIssueLinkModalStore]
|
||||
);
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleLinkOperations: TLinkOperations = useMemo(
|
||||
() => ({
|
||||
create: async (data: Partial<TIssueLink>) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing required fields");
|
||||
await createLink(workspaceSlug, projectId, issueId, data);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The link has been successfully created",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link created",
|
||||
});
|
||||
toggleIssueLinkModal(false);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The link could not be created",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Link not created",
|
||||
});
|
||||
}
|
||||
@ -63,16 +62,16 @@ export const IssueLinkRoot: FC<TIssueLinkRoot> = (props) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing required fields");
|
||||
await updateLink(workspaceSlug, projectId, issueId, linkId, data);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The link has been successfully updated",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link updated",
|
||||
});
|
||||
toggleIssueLinkModal(false);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The link could not be updated",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Link not updated",
|
||||
});
|
||||
}
|
||||
@ -81,22 +80,22 @@ export const IssueLinkRoot: FC<TIssueLinkRoot> = (props) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing required fields");
|
||||
await removeLink(workspaceSlug, projectId, issueId, linkId);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The link has been successfully removed",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link removed",
|
||||
});
|
||||
toggleIssueLinkModal(false);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
message: "The link could not be removed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Link not removed",
|
||||
});
|
||||
}
|
||||
},
|
||||
}),
|
||||
[workspaceSlug, projectId, issueId, createLink, updateLink, removeLink, setToastAlert, toggleIssueLinkModal]
|
||||
[workspaceSlug, projectId, issueId, createLink, updateLink, removeLink, toggleIssueLinkModal]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -75,7 +75,6 @@ export const IssueModuleSelect: React.FC<TIssueModuleSelect> = observer((props)
|
||||
showTooltip
|
||||
multiple
|
||||
/>
|
||||
{isUpdating && <Spinner className="h-4 w-4" />}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -4,7 +4,8 @@ import { observer } from "mobx-react-lite";
|
||||
import { ReactionSelector } from "./reaction-selector";
|
||||
// hooks
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IUser } from "@plane/types";
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
@ -25,7 +26,6 @@ export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props)
|
||||
createCommentReaction,
|
||||
removeCommentReaction,
|
||||
} = useIssueDetail();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const reactionIds = getCommentReactionsByCommentId(commentId);
|
||||
const userReactions = commentReactionsByUser(commentId, currentUser.id).map((r) => r.reaction);
|
||||
@ -36,15 +36,15 @@ export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props)
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !commentId) throw new Error("Missing fields");
|
||||
await createCommentReaction(workspaceSlug, projectId, commentId, reaction);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction created successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Reaction created successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction creation failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Reaction creation failed",
|
||||
});
|
||||
}
|
||||
@ -53,15 +53,15 @@ export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props)
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !commentId || !currentUser?.id) throw new Error("Missing fields");
|
||||
removeCommentReaction(workspaceSlug, projectId, commentId, reaction, currentUser.id);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction removed successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Reaction removed successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction remove failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Reaction remove failed",
|
||||
});
|
||||
}
|
||||
@ -78,7 +78,6 @@ export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props)
|
||||
currentUser,
|
||||
createCommentReaction,
|
||||
removeCommentReaction,
|
||||
setToastAlert,
|
||||
userReactions,
|
||||
]
|
||||
);
|
||||
|
@ -4,7 +4,8 @@ import { observer } from "mobx-react-lite";
|
||||
import { ReactionSelector } from "./reaction-selector";
|
||||
// hooks
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { IUser } from "@plane/types";
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
@ -24,7 +25,6 @@ export const IssueReaction: FC<TIssueReaction> = observer((props) => {
|
||||
createReaction,
|
||||
removeReaction,
|
||||
} = useIssueDetail();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const reactionIds = getReactionsByIssueId(issueId);
|
||||
const userReactions = reactionsByUser(issueId, currentUser.id).map((r) => r.reaction);
|
||||
@ -35,15 +35,15 @@ export const IssueReaction: FC<TIssueReaction> = observer((props) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId) throw new Error("Missing fields");
|
||||
await createReaction(workspaceSlug, projectId, issueId, reaction);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction created successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Reaction created successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction creation failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Reaction creation failed",
|
||||
});
|
||||
}
|
||||
@ -52,15 +52,15 @@ export const IssueReaction: FC<TIssueReaction> = observer((props) => {
|
||||
try {
|
||||
if (!workspaceSlug || !projectId || !issueId || !currentUser?.id) throw new Error("Missing fields");
|
||||
await removeReaction(workspaceSlug, projectId, issueId, reaction, currentUser.id);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction removed successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Reaction removed successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Reaction remove failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Reaction remove failed",
|
||||
});
|
||||
}
|
||||
@ -70,7 +70,7 @@ export const IssueReaction: FC<TIssueReaction> = observer((props) => {
|
||||
else await issueReactionOperations.create(reaction);
|
||||
},
|
||||
}),
|
||||
[workspaceSlug, projectId, issueId, currentUser, createReaction, removeReaction, setToastAlert, userReactions]
|
||||
[workspaceSlug, projectId, issueId, currentUser, createReaction, removeReaction, userReactions]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -4,11 +4,10 @@ import { observer } from "mobx-react-lite";
|
||||
import { CircleDot, CopyPlus, Pencil, X, XCircle } from "lucide-react";
|
||||
// hooks
|
||||
import { useIssueDetail, useIssues, useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { ExistingIssuesListModal } from "components/core";
|
||||
// ui
|
||||
import { RelatedIcon, Tooltip } from "@plane/ui";
|
||||
import { RelatedIcon, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { cn } from "helpers/common.helper";
|
||||
// types
|
||||
@ -60,15 +59,13 @@ export const IssueRelationSelect: React.FC<TIssueRelationSelect> = observer((pro
|
||||
toggleRelationModal,
|
||||
} = useIssueDetail();
|
||||
const { issueMap } = useIssues();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const relationIssueIds = getRelationByIssueIdRelationType(issueId, relationKey);
|
||||
|
||||
const onSubmit = async (data: ISearchIssueResponse[]) => {
|
||||
if (data.length === 0) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Please select at least one issue.",
|
||||
});
|
||||
|
@ -10,9 +10,10 @@ import { EmptyState } from "components/common";
|
||||
import emptyIssue from "public/empty-state/issue.svg";
|
||||
// hooks
|
||||
import { useApplication, useEventTracker, useIssueDetail, useIssues, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
// ui
|
||||
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
||||
// constants
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
import { EIssuesStoreType } from "constants/issue";
|
||||
@ -21,13 +22,7 @@ import { observer } from "mobx-react";
|
||||
|
||||
export type TIssueOperations = {
|
||||
fetch: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
update: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
showToast?: boolean
|
||||
) => Promise<void>;
|
||||
update: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||
remove: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
archive?: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
restore?: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
@ -76,7 +71,6 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
issues: { removeIssue: removeArchivedIssue },
|
||||
} = useIssues(EIssuesStoreType.ARCHIVED);
|
||||
const { captureIssueEvent } = useEventTracker();
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
@ -91,22 +85,9 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
console.error("Error fetching the parent issue");
|
||||
}
|
||||
},
|
||||
update: async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
showToast: boolean = true
|
||||
) => {
|
||||
update: async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => {
|
||||
try {
|
||||
await updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
if (showToast) {
|
||||
setToastAlert({
|
||||
title: "Issue updated successfully",
|
||||
type: "success",
|
||||
message: "Issue updated successfully",
|
||||
});
|
||||
}
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" },
|
||||
@ -126,9 +107,9 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue update failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Issue update failed",
|
||||
});
|
||||
}
|
||||
@ -138,9 +119,9 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
let response;
|
||||
if (is_archived) response = await removeArchivedIssue(workspaceSlug, projectId, issueId);
|
||||
else response = await removeIssue(workspaceSlug, projectId, issueId);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue deleted successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Issue deleted successfully",
|
||||
});
|
||||
captureIssueEvent({
|
||||
@ -149,9 +130,9 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue delete failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Issue delete failed",
|
||||
});
|
||||
captureIssueEvent({
|
||||
@ -164,8 +145,8 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
archive: async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
await archiveIssue(workspaceSlug, projectId, issueId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Issue archived successfully.",
|
||||
});
|
||||
@ -175,8 +156,8 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issue could not be archived. Please try again.",
|
||||
});
|
||||
@ -189,12 +170,19 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
||||
try {
|
||||
await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||
setToastAlert({
|
||||
title: "Cycle added to issue successfully",
|
||||
type: "success",
|
||||
message: "Issue added to issue successfully",
|
||||
const addToCyclePromise = addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||
setPromiseToast(addToCyclePromise, {
|
||||
loading: "Adding cycle to issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle added to issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Cycle add to issue failed",
|
||||
},
|
||||
});
|
||||
await addToCyclePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...issueIds, state: "SUCCESS", element: "Issue detail page" },
|
||||
@ -214,21 +202,23 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
title: "Cycle add to issue failed",
|
||||
type: "error",
|
||||
message: "Cycle add to issue failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
removeIssueFromCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||
setToastAlert({
|
||||
title: "Cycle removed from issue successfully",
|
||||
type: "success",
|
||||
message: "Cycle removed from issue successfully",
|
||||
const removeFromCyclePromise = removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||
setPromiseToast(removeFromCyclePromise, {
|
||||
loading: "Removing cycle from issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle removed from issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Cycle remove from issue failed",
|
||||
},
|
||||
});
|
||||
const response = await removeFromCyclePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...response, state: "SUCCESS", element: "Issue detail page" },
|
||||
@ -248,21 +238,23 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
title: "Cycle remove from issue failed",
|
||||
type: "error",
|
||||
message: "Cycle remove from issue failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
addModulesToIssue: async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||
try {
|
||||
const response = await addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setToastAlert({
|
||||
title: "Module added to issue successfully",
|
||||
type: "success",
|
||||
message: "Module added to issue successfully",
|
||||
const addToModulePromise = addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setPromiseToast(addToModulePromise, {
|
||||
loading: "Adding module to issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Module added to issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Module add to issue failed",
|
||||
},
|
||||
});
|
||||
const response = await addToModulePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...response, state: "SUCCESS", element: "Issue detail page" },
|
||||
@ -282,21 +274,23 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
title: "Module add to issue failed",
|
||||
type: "error",
|
||||
message: "Module add to issue failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
removeIssueFromModule: async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => {
|
||||
try {
|
||||
await removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
||||
setToastAlert({
|
||||
title: "Module removed from issue successfully",
|
||||
type: "success",
|
||||
message: "Module removed from issue successfully",
|
||||
const removeFromModulePromise = removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
||||
setPromiseToast(removeFromModulePromise, {
|
||||
loading: "Removing module from issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Module removed from issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Module remove from issue failed",
|
||||
},
|
||||
});
|
||||
await removeFromModulePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
|
||||
@ -316,11 +310,6 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
title: "Module remove from issue failed",
|
||||
type: "error",
|
||||
message: "Module remove from issue failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
removeModulesFromIssue: async (
|
||||
@ -329,20 +318,19 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
issueId: string,
|
||||
moduleIds: string[]
|
||||
) => {
|
||||
try {
|
||||
await removeModulesFromIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Successful!",
|
||||
message: "Issue removed from module successfully.",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
const removeModulesFromIssuePromise = removeModulesFromIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setPromiseToast(removeModulesFromIssuePromise, {
|
||||
loading: "Removing module from issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Module removed from issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: "Issue could not be removed from module. Please try again.",
|
||||
message: () => "Module remove from issue failed",
|
||||
},
|
||||
});
|
||||
}
|
||||
await removeModulesFromIssuePromise;
|
||||
},
|
||||
}),
|
||||
[
|
||||
@ -357,7 +345,6 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||
addModulesToIssue,
|
||||
removeIssueFromModule,
|
||||
removeModulesFromIssue,
|
||||
setToastAlert,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -16,7 +16,6 @@ import {
|
||||
} from "lucide-react";
|
||||
// hooks
|
||||
import { useEstimate, useIssueDetail, useProject, useProjectState, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import {
|
||||
DeleteIssueModal,
|
||||
@ -30,8 +29,18 @@ import {
|
||||
} from "components/issues";
|
||||
import { IssueSubscription } from "./subscription";
|
||||
import { DateDropdown, EstimateDropdown, PriorityDropdown, MemberDropdown, StateDropdown } from "components/dropdowns";
|
||||
// icons
|
||||
import { ArchiveIcon, ContrastIcon, DiceIcon, DoubleCircleIcon, RelatedIcon, Tooltip, UserGroupIcon } from "@plane/ui";
|
||||
// ui
|
||||
import {
|
||||
ArchiveIcon,
|
||||
ContrastIcon,
|
||||
DiceIcon,
|
||||
DoubleCircleIcon,
|
||||
RelatedIcon,
|
||||
Tooltip,
|
||||
UserGroupIcon,
|
||||
TOAST_TYPE,
|
||||
setToast,
|
||||
} from "@plane/ui";
|
||||
// helpers
|
||||
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
|
||||
import { copyTextToClipboard } from "helpers/string.helper";
|
||||
@ -61,7 +70,6 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
const { getProjectById } = useProject();
|
||||
const { currentUser } = useUser();
|
||||
const { areEstimatesEnabledForCurrentProject } = useEstimate();
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
issue: { getIssueById },
|
||||
} = useIssueDetail();
|
||||
@ -73,8 +81,8 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
const handleCopyText = () => {
|
||||
const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
|
||||
copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`).then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link Copied!",
|
||||
message: "Issue link copied to clipboard.",
|
||||
});
|
||||
|
@ -2,10 +2,9 @@ import { Bell, BellOff } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { FC, useState } from "react";
|
||||
// UI
|
||||
import { Button, Loader } from "@plane/ui";
|
||||
import { Button, Loader, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// hooks
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import isNil from "lodash/isNil";
|
||||
|
||||
export type TIssueSubscription = {
|
||||
@ -22,7 +21,6 @@ export const IssueSubscription: FC<TIssueSubscription> = observer((props) => {
|
||||
createSubscription,
|
||||
removeSubscription,
|
||||
} = useIssueDetail();
|
||||
const { setToastAlert } = useToast();
|
||||
// state
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
@ -33,16 +31,16 @@ export const IssueSubscription: FC<TIssueSubscription> = observer((props) => {
|
||||
try {
|
||||
if (isSubscribed) await removeSubscription(workspaceSlug, projectId, issueId);
|
||||
else await createSubscription(workspaceSlug, projectId, issueId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: `Issue ${isSubscribed ? `unsubscribed` : `subscribed`} successfully.!`,
|
||||
message: `Issue ${isSubscribed ? `unsubscribed` : `subscribed`} successfully.!`,
|
||||
});
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error",
|
||||
message: "Something went wrong. Please try again later.",
|
||||
});
|
||||
|
@ -4,8 +4,8 @@ import { observer } from "mobx-react-lite";
|
||||
import { DragDropContext, DropResult } from "@hello-pangea/dnd";
|
||||
// components
|
||||
import { CalendarChart } from "components/issues";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TGroupedIssues, TIssue } from "@plane/types";
|
||||
import { IQuickActionProps } from "../list/list-view-types";
|
||||
@ -41,7 +41,6 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
const { issueMap } = useIssues();
|
||||
const {
|
||||
membership: { currentProjectRole },
|
||||
@ -73,9 +72,9 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
|
||||
groupedIssueIds,
|
||||
viewId
|
||||
).catch((err) => {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Error",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: err.detail ?? "Failed to perform this action",
|
||||
});
|
||||
});
|
||||
|
@ -4,13 +4,14 @@ import { useForm } from "react-hook-form";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useEventTracker, useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useKeypress from "hooks/use-keypress";
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
// helpers
|
||||
import { createIssuePayload } from "helpers/issue.helper";
|
||||
// icons
|
||||
import { PlusIcon } from "lucide-react";
|
||||
// ui
|
||||
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
// constants
|
||||
@ -71,8 +72,6 @@ export const CalendarQuickAddIssueForm: React.FC<Props> = observer((props) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
// states
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// derived values
|
||||
const projectDetail = projectId ? getProjectById(projectId.toString()) : null;
|
||||
@ -102,13 +101,13 @@ export const CalendarQuickAddIssueForm: React.FC<Props> = observer((props) => {
|
||||
Object.keys(errors).forEach((key) => {
|
||||
const error = errors[key as keyof TIssue];
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: error?.message?.toString() || "Some error occurred. Please try again.",
|
||||
});
|
||||
});
|
||||
}, [errors, setToastAlert]);
|
||||
}, [errors]);
|
||||
|
||||
const onSubmitHandler = async (formData: TIssue) => {
|
||||
if (isSubmitting || !workspaceSlug || !projectId) return;
|
||||
@ -120,38 +119,41 @@ export const CalendarQuickAddIssueForm: React.FC<Props> = observer((props) => {
|
||||
...formData,
|
||||
});
|
||||
|
||||
try {
|
||||
quickAddCallback &&
|
||||
(await quickAddCallback(
|
||||
if (quickAddCallback) {
|
||||
const quickAddPromise = quickAddCallback(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
{
|
||||
...payload,
|
||||
},
|
||||
viewId
|
||||
).then((res) => {
|
||||
);
|
||||
setPromiseToast<any>(quickAddPromise, {
|
||||
loading: "Adding issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Issue created successfully.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: (err) => err?.message || "Some error occurred. Please try again.",
|
||||
},
|
||||
});
|
||||
|
||||
await quickAddPromise
|
||||
.then((res) => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...res, state: "SUCCESS", element: "Calendar quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
}));
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Issue created successfully.",
|
||||
});
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
})
|
||||
.catch(() => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...payload, state: "FAILED", element: "Calendar quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: err?.message || "Some error occurred. Please try again.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -4,7 +4,8 @@ import { PlusIcon } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
// hooks
|
||||
import { useApplication, useEventTracker, useIssueDetail, useIssues, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { ExistingIssuesListModal } from "components/core";
|
||||
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
||||
@ -53,16 +54,14 @@ export const CycleEmptyState: React.FC<Props> = observer((props) => {
|
||||
currentUser,
|
||||
} = useUser();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleAddIssuesToCycle = async (data: ISearchIssueResponse[]) => {
|
||||
if (!workspaceSlug || !projectId || !cycleId) return;
|
||||
|
||||
const issueIds = data.map((i) => i.id);
|
||||
|
||||
await issues.addIssueToCycle(workspaceSlug.toString(), projectId, cycleId.toString(), issueIds).catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Selected issues could not be added to the cycle. Please try again.",
|
||||
});
|
||||
|
@ -4,7 +4,8 @@ import { PlusIcon } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
// hooks
|
||||
import { useApplication, useEventTracker, useIssues, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { ExistingIssuesListModal } from "components/core";
|
||||
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
||||
@ -51,8 +52,6 @@ export const ModuleEmptyState: React.FC<Props> = observer((props) => {
|
||||
membership: { currentProjectRole: userRole },
|
||||
currentUser,
|
||||
} = useUser();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const handleAddIssuesToModule = async (data: ISearchIssueResponse[]) => {
|
||||
if (!workspaceSlug || !projectId || !moduleId) return;
|
||||
@ -61,8 +60,8 @@ export const ModuleEmptyState: React.FC<Props> = observer((props) => {
|
||||
await issues
|
||||
.addIssuesToModule(workspaceSlug.toString(), projectId?.toString(), moduleId.toString(), issueIds)
|
||||
.catch(() =>
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Selected issues could not be added to the module. Please try again.",
|
||||
})
|
||||
|
@ -5,13 +5,14 @@ import { observer } from "mobx-react-lite";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
// hooks
|
||||
import { useEventTracker, useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useKeypress from "hooks/use-keypress";
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
// helpers
|
||||
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
|
||||
import { createIssuePayload } from "helpers/issue.helper";
|
||||
import { cn } from "helpers/common.helper";
|
||||
// ui
|
||||
import { setPromiseToast } from "@plane/ui";
|
||||
// types
|
||||
import { IProject, TIssue } from "@plane/types";
|
||||
// constants
|
||||
@ -70,7 +71,6 @@ export const GanttQuickAddIssueForm: React.FC<IGanttQuickAddIssueForm> = observe
|
||||
// hooks
|
||||
const { getProjectById } = useProject();
|
||||
const { captureIssueEvent } = useEventTracker();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const projectDetail = (projectId && getProjectById(projectId.toString())) || undefined;
|
||||
|
||||
@ -110,30 +110,34 @@ export const GanttQuickAddIssueForm: React.FC<IGanttQuickAddIssueForm> = observe
|
||||
target_date: renderFormattedPayloadDate(targetDate),
|
||||
});
|
||||
|
||||
try {
|
||||
quickAddCallback &&
|
||||
(await quickAddCallback(workspaceSlug.toString(), projectId.toString(), { ...payload }, viewId).then((res) => {
|
||||
if (quickAddCallback) {
|
||||
const quickAddPromise = quickAddCallback(workspaceSlug.toString(), projectId.toString(), { ...payload }, viewId);
|
||||
setPromiseToast<any>(quickAddPromise, {
|
||||
loading: "Adding issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Issue created successfully.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: (err) => err?.message || "Some error occurred. Please try again.",
|
||||
},
|
||||
});
|
||||
|
||||
await quickAddPromise
|
||||
.then((res) => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...res, state: "SUCCESS", element: "Gantt quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
}));
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Issue created successfully.",
|
||||
});
|
||||
} catch (err: any) {
|
||||
})
|
||||
.catch(() => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...payload, state: "FAILED", element: "Gantt quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: err?.message || "Some error occurred. Please try again.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -4,9 +4,8 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useEventTracker, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Spinner } from "@plane/ui";
|
||||
import { Spinner, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
import { EIssueActions } from "../types";
|
||||
@ -80,8 +79,6 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
||||
} = useUser();
|
||||
const { captureIssueEvent } = useEventTracker();
|
||||
const { issueMap } = useIssues();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const issueIds = issues?.groupedIssueIds || [];
|
||||
|
||||
@ -159,9 +156,9 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
|
||||
issueIds,
|
||||
viewId
|
||||
).catch((err) => {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Error",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: err.detail ?? "Failed to perform this action",
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
import React, { FC } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
// ui
|
||||
import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
import { ExistingIssuesListModal } from "components/core";
|
||||
import { CreateUpdateIssueModal } from "components/issues";
|
||||
// lucide icons
|
||||
import { Minimize2, Maximize2, Circle, Plus } from "lucide-react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker } from "hooks/store";
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
@ -56,8 +56,6 @@ export const HeaderGroupByCard: FC<IHeaderGroupByCard> = observer((props) => {
|
||||
|
||||
const isDraftIssue = router.pathname.includes("draft-issue");
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const renderExistingIssueModal = moduleId || cycleId;
|
||||
const ExistingIssuesListModalPayload = moduleId ? { module: moduleId.toString() } : { cycle: true };
|
||||
|
||||
@ -69,8 +67,8 @@ export const HeaderGroupByCard: FC<IHeaderGroupByCard> = observer((props) => {
|
||||
try {
|
||||
addIssuesToView && addIssuesToView(issues);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Selected issues could not be added to the cycle. Please try again.",
|
||||
});
|
||||
|
@ -5,11 +5,12 @@ import { observer } from "mobx-react-lite";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
// hooks
|
||||
import { useEventTracker, useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useKeypress from "hooks/use-keypress";
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
// helpers
|
||||
import { createIssuePayload } from "helpers/issue.helper";
|
||||
// ui
|
||||
import { setPromiseToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
// constants
|
||||
@ -73,7 +74,6 @@ export const KanBanQuickAddIssueForm: React.FC<IKanBanQuickAddIssueForm> = obser
|
||||
|
||||
useKeypress("Escape", handleClose);
|
||||
useOutsideClickDetector(ref, handleClose);
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const {
|
||||
reset,
|
||||
@ -97,38 +97,41 @@ export const KanBanQuickAddIssueForm: React.FC<IKanBanQuickAddIssueForm> = obser
|
||||
...formData,
|
||||
});
|
||||
|
||||
try {
|
||||
quickAddCallback &&
|
||||
(await quickAddCallback(
|
||||
if (quickAddCallback) {
|
||||
const quickAddPromise = quickAddCallback(
|
||||
workspaceSlug.toString(),
|
||||
projectId.toString(),
|
||||
{
|
||||
...payload,
|
||||
},
|
||||
viewId
|
||||
).then((res) => {
|
||||
);
|
||||
setPromiseToast<any>(quickAddPromise, {
|
||||
loading: "Adding issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Issue created successfully.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: (err) => err?.message || "Some error occurred. Please try again.",
|
||||
},
|
||||
});
|
||||
|
||||
await quickAddPromise
|
||||
.then((res) => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...res, state: "SUCCESS", element: "Kanban quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
}));
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Issue created successfully.",
|
||||
});
|
||||
} catch (err: any) {
|
||||
})
|
||||
.catch(() => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...payload, state: "FAILED", element: "Kanban quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
console.error(err);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: err?.message || "Some error occurred. Please try again.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -4,14 +4,14 @@ import { CircleDashed, Plus } from "lucide-react";
|
||||
// components
|
||||
import { CreateUpdateIssueModal } from "components/issues";
|
||||
import { ExistingIssuesListModal } from "components/core";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
// ui
|
||||
import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useEventTracker } from "hooks/store";
|
||||
// types
|
||||
import { TIssue, ISearchIssueResponse } from "@plane/types";
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useState } from "react";
|
||||
import { TCreateModalStoreTypes } from "constants/issue";
|
||||
|
||||
@ -38,8 +38,6 @@ export const HeaderGroupByCard = observer(
|
||||
|
||||
const isDraftIssue = router.pathname.includes("draft-issue");
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const renderExistingIssueModal = moduleId || cycleId;
|
||||
const ExistingIssuesListModalPayload = moduleId ? { module: moduleId.toString() } : { cycle: true };
|
||||
|
||||
@ -51,8 +49,8 @@ export const HeaderGroupByCard = observer(
|
||||
try {
|
||||
addIssuesToView && addIssuesToView(issues);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Selected issues could not be added to the cycle. Please try again.",
|
||||
});
|
||||
|
@ -5,12 +5,13 @@ import { PlusIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useEventTracker, useProject } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useKeypress from "hooks/use-keypress";
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
// constants
|
||||
import { TIssue, IProject } from "@plane/types";
|
||||
// ui
|
||||
import { setPromiseToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue, IProject } from "@plane/types";
|
||||
// helper
|
||||
import { createIssuePayload } from "helpers/issue.helper";
|
||||
// constants
|
||||
import { ISSUE_CREATED } from "constants/event-tracker";
|
||||
@ -77,7 +78,6 @@ export const ListQuickAddIssueForm: FC<IListQuickAddIssueForm> = observer((props
|
||||
|
||||
useKeypress("Escape", handleClose);
|
||||
useOutsideClickDetector(ref, handleClose);
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const {
|
||||
reset,
|
||||
@ -101,30 +101,34 @@ export const ListQuickAddIssueForm: FC<IListQuickAddIssueForm> = observer((props
|
||||
...formData,
|
||||
});
|
||||
|
||||
try {
|
||||
quickAddCallback &&
|
||||
(await quickAddCallback(workspaceSlug.toString(), projectId.toString(), { ...payload }, viewId).then((res) => {
|
||||
if (quickAddCallback) {
|
||||
const quickAddPromise = quickAddCallback(workspaceSlug.toString(), projectId.toString(), { ...payload }, viewId);
|
||||
setPromiseToast<any>(quickAddPromise, {
|
||||
loading: "Adding issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Issue created successfully.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: (err) => err?.message || "Some error occurred. Please try again.",
|
||||
},
|
||||
});
|
||||
|
||||
await quickAddPromise
|
||||
.then((res) => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...res, state: "SUCCESS", element: "List quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
}));
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Issue created successfully.",
|
||||
});
|
||||
} catch (err: any) {
|
||||
})
|
||||
.catch(() => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...payload, state: "FAILED", element: "List quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: err?.message || "Some error occurred. Please try again.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { ArchiveIcon, CustomMenu } from "@plane/ui";
|
||||
import { observer } from "mobx-react";
|
||||
import { Copy, ExternalLink, Link, Pencil, Trash2 } from "lucide-react";
|
||||
import omit from "lodash/omit";
|
||||
import { observer } from "mobx-react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker, useProjectState } from "hooks/store";
|
||||
// ui
|
||||
import { ArchiveIcon, CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// helpers
|
||||
@ -39,8 +39,6 @@ export const AllIssueQuickActions: React.FC<IQuickActionProps> = observer((props
|
||||
// store hooks
|
||||
const { setTrackElement } = useEventTracker();
|
||||
const { getStateById } = useProjectState();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// derived values
|
||||
const stateDetails = getStateById(issue.state_id);
|
||||
const isEditingAllowed = !readOnly;
|
||||
@ -54,8 +52,8 @@ export const AllIssueQuickActions: React.FC<IQuickActionProps> = observer((props
|
||||
const handleOpenInNewTab = () => window.open(`/${issueLink}`, "_blank");
|
||||
const handleCopyIssueLink = () =>
|
||||
copyUrlToClipboard(issueLink).then(() =>
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link copied",
|
||||
message: "Issue link copied to clipboard",
|
||||
})
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
import { ExternalLink, Link, RotateCcw, Trash2 } from "lucide-react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker, useIssues, useUser } from "hooks/store";
|
||||
// ui
|
||||
import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { DeleteIssueModal } from "components/issues";
|
||||
// helpers
|
||||
@ -32,16 +32,14 @@ export const ArchivedIssueQuickActions: React.FC<IQuickActionProps> = (props) =>
|
||||
// auth
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER && !readOnly;
|
||||
const isRestoringAllowed = handleRestore && isEditingAllowed;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const issueLink = `${workspaceSlug}/projects/${issue.project_id}/archived-issues/${issue.id}`;
|
||||
|
||||
const handleOpenInNewTab = () => window.open(`/${issueLink}`, "_blank");
|
||||
const handleCopyIssueLink = () =>
|
||||
copyUrlToClipboard(issueLink).then(() =>
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link copied",
|
||||
message: "Issue link copied to clipboard",
|
||||
})
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { ArchiveIcon, CustomMenu } from "@plane/ui";
|
||||
import { observer } from "mobx-react";
|
||||
import { Copy, ExternalLink, Link, Pencil, Trash2, XCircle } from "lucide-react";
|
||||
import omit from "lodash/omit";
|
||||
import { observer } from "mobx-react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker, useIssues, useProjectState, useUser } from "hooks/store";
|
||||
// ui
|
||||
import { ArchiveIcon, CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// icons
|
||||
import { Copy, ExternalLink, Link, Pencil, Trash2, XCircle } from "lucide-react";
|
||||
// components
|
||||
import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// helpers
|
||||
@ -45,8 +46,6 @@ export const CycleIssueQuickActions: React.FC<IQuickActionProps> = observer((pro
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const { getStateById } = useProjectState();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// derived values
|
||||
const stateDetails = getStateById(issue.state_id);
|
||||
// auth
|
||||
@ -64,8 +63,8 @@ export const CycleIssueQuickActions: React.FC<IQuickActionProps> = observer((pro
|
||||
|
||||
const handleCopyIssueLink = () =>
|
||||
copyUrlToClipboard(issueLink).then(() =>
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link copied",
|
||||
message: "Issue link copied to clipboard",
|
||||
})
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { ArchiveIcon, CustomMenu } from "@plane/ui";
|
||||
import { observer } from "mobx-react";
|
||||
import { Copy, ExternalLink, Link, Pencil, Trash2, XCircle } from "lucide-react";
|
||||
import omit from "lodash/omit";
|
||||
import { observer } from "mobx-react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useIssues, useEventTracker, useUser, useProjectState } from "hooks/store";
|
||||
// ui
|
||||
import { ArchiveIcon, CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
import { Copy, ExternalLink, Link, Pencil, Trash2, XCircle } from "lucide-react";
|
||||
// components
|
||||
import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// helpers
|
||||
@ -45,8 +45,6 @@ export const ModuleIssueQuickActions: React.FC<IQuickActionProps> = observer((pr
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const { getStateById } = useProjectState();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// derived values
|
||||
const stateDetails = getStateById(issue.state_id);
|
||||
// auth
|
||||
@ -64,8 +62,8 @@ export const ModuleIssueQuickActions: React.FC<IQuickActionProps> = observer((pr
|
||||
|
||||
const handleCopyIssueLink = () =>
|
||||
copyUrlToClipboard(issueLink).then(() =>
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link copied",
|
||||
message: "Issue link copied to clipboard",
|
||||
})
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { ArchiveIcon, CustomMenu } from "@plane/ui";
|
||||
import { observer } from "mobx-react";
|
||||
import { Copy, ExternalLink, Link, Pencil, Trash2 } from "lucide-react";
|
||||
import omit from "lodash/omit";
|
||||
import { observer } from "mobx-react";
|
||||
// hooks
|
||||
import { useEventTracker, useIssues, useProjectState, useUser } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { ArchiveIcon, CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
import { Copy, ExternalLink, Link, Pencil, Trash2 } from "lucide-react";
|
||||
// components
|
||||
import { ArchiveIssueModal, CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// helpers
|
||||
@ -54,16 +54,14 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = observer((p
|
||||
!!stateDetails && [STATE_GROUPS.completed.key, STATE_GROUPS.cancelled.key].includes(stateDetails?.group);
|
||||
const isDeletingAllowed = isEditingAllowed;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const issueLink = `${workspaceSlug}/projects/${issue.project_id}/issues/${issue.id}`;
|
||||
|
||||
const handleOpenInNewTab = () => window.open(`/${issueLink}`, "_blank");
|
||||
|
||||
const handleCopyIssueLink = () =>
|
||||
copyUrlToClipboard(issueLink).then(() =>
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link copied",
|
||||
message: "Issue link copied to clipboard",
|
||||
})
|
||||
|
@ -5,11 +5,12 @@ import { observer } from "mobx-react-lite";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
// hooks
|
||||
import { useEventTracker, useProject, useWorkspace } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useKeypress from "hooks/use-keypress";
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
// helpers
|
||||
import { createIssuePayload } from "helpers/issue.helper";
|
||||
// ui
|
||||
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
// constants
|
||||
@ -84,7 +85,6 @@ export const SpreadsheetQuickAddIssueForm: React.FC<Props> = observer((props) =>
|
||||
// hooks
|
||||
useKeypress("Escape", handleClose);
|
||||
useOutsideClickDetector(ref, handleClose);
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
useEffect(() => {
|
||||
setFocus("name");
|
||||
@ -100,13 +100,13 @@ export const SpreadsheetQuickAddIssueForm: React.FC<Props> = observer((props) =>
|
||||
Object.keys(errors).forEach((key) => {
|
||||
const error = errors[key as keyof TIssue];
|
||||
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: error?.message?.toString() || "Some error occurred. Please try again.",
|
||||
});
|
||||
});
|
||||
}, [errors, setToastAlert]);
|
||||
}, [errors]);
|
||||
|
||||
// const onSubmitHandler = async (formData: TIssue) => {
|
||||
// if (isSubmitting || !workspaceSlug || !projectId) return;
|
||||
@ -130,8 +130,8 @@ export const SpreadsheetQuickAddIssueForm: React.FC<Props> = observer((props) =>
|
||||
// payload
|
||||
// );
|
||||
|
||||
// setToastAlert({
|
||||
// type: "success",
|
||||
// setToast({
|
||||
// type: TOAST_TYPE.SUCCESS,
|
||||
// title: "Success!",
|
||||
// message: "Issue created successfully.",
|
||||
// });
|
||||
@ -140,8 +140,8 @@ export const SpreadsheetQuickAddIssueForm: React.FC<Props> = observer((props) =>
|
||||
// const error = err?.[key];
|
||||
// const errorTitle = error ? (Array.isArray(error) ? error.join(", ") : error) : null;
|
||||
|
||||
// setToastAlert({
|
||||
// type: "error",
|
||||
// setToast({
|
||||
// type: TOAST_TYPE.ERROR,
|
||||
// title: "Error!",
|
||||
// message: errorTitle || "Some error occurred. Please try again.",
|
||||
// });
|
||||
@ -159,33 +159,40 @@ export const SpreadsheetQuickAddIssueForm: React.FC<Props> = observer((props) =>
|
||||
...formData,
|
||||
});
|
||||
|
||||
try {
|
||||
quickAddCallback &&
|
||||
(await quickAddCallback(currentWorkspace.slug, currentProjectDetails.id, { ...payload } as TIssue, viewId).then(
|
||||
(res) => {
|
||||
if (quickAddCallback) {
|
||||
const quickAddPromise = quickAddCallback(
|
||||
currentWorkspace.slug,
|
||||
currentProjectDetails.id,
|
||||
{ ...payload } as TIssue,
|
||||
viewId
|
||||
);
|
||||
setPromiseToast<any>(quickAddPromise, {
|
||||
loading: "Adding issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Issue created successfully.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: (err) => err?.message || "Some error occurred. Please try again.",
|
||||
},
|
||||
});
|
||||
|
||||
await quickAddPromise
|
||||
.then((res) => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...res, state: "SUCCESS", element: "Spreadsheet quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
}
|
||||
));
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Issue created successfully.",
|
||||
});
|
||||
} catch (err: any) {
|
||||
})
|
||||
.catch((err) => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_CREATED,
|
||||
payload: { ...payload, state: "FAILED", element: "Spreadsheet quick add" },
|
||||
path: router.asPath,
|
||||
});
|
||||
console.error(err);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: err?.message || "Some error occurred. Please try again.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -2,10 +2,11 @@ import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker } from "hooks/store";
|
||||
// services
|
||||
import { IssueDraftService } from "services/issue";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { IssueFormRoot } from "components/issues/issue-modal/form";
|
||||
import { ConfirmIssueDiscard } from "components/issues";
|
||||
@ -43,8 +44,6 @@ export const DraftIssueLayout: React.FC<DraftIssueProps> = observer((props) => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// store hooks
|
||||
const { captureIssueEvent } = useEventTracker();
|
||||
|
||||
@ -61,8 +60,8 @@ export const DraftIssueLayout: React.FC<DraftIssueProps> = observer((props) => {
|
||||
await issueDraftService
|
||||
.createDraftIssue(workspaceSlug.toString(), projectId.toString(), payload)
|
||||
.then((res) => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Draft Issue created successfully.",
|
||||
});
|
||||
@ -76,8 +75,8 @@ export const DraftIssueLayout: React.FC<DraftIssueProps> = observer((props) => {
|
||||
onClose(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issue could not be created. Please try again.",
|
||||
});
|
||||
|
@ -7,7 +7,6 @@ import { LayoutPanelTop, Sparkle, X } from "lucide-react";
|
||||
import { RichTextEditorWithRef } from "@plane/rich-text-editor";
|
||||
// hooks
|
||||
import { useApplication, useEstimate, useIssueDetail, useMention, useProject, useWorkspace } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// services
|
||||
import { AIService } from "services/ai.service";
|
||||
import { FileService } from "services/file.service";
|
||||
@ -27,7 +26,7 @@ import {
|
||||
StateDropdown,
|
||||
} from "components/dropdowns";
|
||||
// ui
|
||||
import { Button, CustomMenu, Input, Loader, ToggleSwitch } from "@plane/ui";
|
||||
import { Button, CustomMenu, Input, Loader, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { renderFormattedPayloadDate } from "helpers/date-time.helper";
|
||||
// types
|
||||
@ -125,8 +124,6 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
const {
|
||||
issue: { getIssueById },
|
||||
} = useIssueDetail();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// form info
|
||||
const {
|
||||
formState: { errors, isDirty, isSubmitting },
|
||||
@ -199,8 +196,8 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.response === "")
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message:
|
||||
"Issue title isn't informative enough to generate the description. Please try with a different title.",
|
||||
@ -211,14 +208,14 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
const error = err?.data?.error;
|
||||
|
||||
if (err.status === 429)
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: error || "You have reached the maximum number of requests of 50 requests per month per user.",
|
||||
});
|
||||
else
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: error || "Some error occurred. Please try again.",
|
||||
});
|
||||
|
@ -13,11 +13,12 @@ import {
|
||||
useWorkspace,
|
||||
useIssueDetail,
|
||||
} from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useLocalStorage from "hooks/use-local-storage";
|
||||
// components
|
||||
import { DraftIssueLayout } from "./draft-issue-layout";
|
||||
import { IssueFormRoot } from "./form";
|
||||
// ui
|
||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import type { TIssue } from "@plane/types";
|
||||
// constants
|
||||
@ -89,8 +90,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
||||
};
|
||||
// router
|
||||
const router = useRouter();
|
||||
// toast alert
|
||||
const { setToastAlert } = useToast();
|
||||
// local storage
|
||||
const { storedValue: localStorageDraftIssues, setValue: setLocalStorageDraftIssue } = useLocalStorage<
|
||||
Record<string, Partial<TIssue>>
|
||||
@ -186,9 +185,8 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
||||
await addIssueToCycle(response, payload.cycle_id);
|
||||
if (payload.module_ids && payload.module_ids.length > 0 && storeType !== EIssuesStoreType.MODULE)
|
||||
await addIssueToModule(response, payload.module_ids);
|
||||
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Issue created successfully.",
|
||||
});
|
||||
@ -200,8 +198,8 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
||||
!createMore && handleClose();
|
||||
return response;
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issue could not be created. Please try again.",
|
||||
});
|
||||
@ -221,8 +219,8 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
||||
? await draftIssues.updateIssue(workspaceSlug, payload.project_id, data.id, payload)
|
||||
: await currentIssueStore.updateIssue(workspaceSlug, payload.project_id, data.id, payload, viewId);
|
||||
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Issue updated successfully.",
|
||||
});
|
||||
@ -233,8 +231,8 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
||||
});
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issue could not be created. Please try again.",
|
||||
});
|
||||
|
@ -3,11 +3,18 @@ import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react";
|
||||
import { MoveRight, MoveDiagonal, Link2, Trash2, RotateCcw } from "lucide-react";
|
||||
// ui
|
||||
import { ArchiveIcon, CenterPanelIcon, CustomSelect, FullScreenPanelIcon, SidePanelIcon, Tooltip } from "@plane/ui";
|
||||
import {
|
||||
ArchiveIcon,
|
||||
CenterPanelIcon,
|
||||
CustomSelect,
|
||||
FullScreenPanelIcon,
|
||||
SidePanelIcon,
|
||||
Tooltip,
|
||||
TOAST_TYPE,
|
||||
setToast,
|
||||
} from "@plane/ui";
|
||||
// helpers
|
||||
import { copyUrlToClipboard } from "helpers/string.helper";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// store hooks
|
||||
import { useIssueDetail, useProjectState, useUser } from "hooks/store";
|
||||
// helpers
|
||||
@ -74,8 +81,6 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
|
||||
issue: { getIssueById },
|
||||
} = useIssueDetail();
|
||||
const { getStateById } = useProjectState();
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
// derived values
|
||||
const issueDetails = getIssueById(issueId);
|
||||
const stateDetails = issueDetails ? getStateById(issueDetails?.state_id) : undefined;
|
||||
@ -87,8 +92,8 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
copyUrlToClipboard(issueLink).then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link Copied!",
|
||||
message: "Issue link copied to clipboard.",
|
||||
});
|
||||
|
@ -2,8 +2,9 @@ import { FC, useEffect, useState, useMemo } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useEventTracker, useIssueDetail, useIssues, useUser } from "hooks/store";
|
||||
// ui
|
||||
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { IssueView } from "components/issues";
|
||||
// types
|
||||
@ -20,13 +21,7 @@ interface IIssuePeekOverview {
|
||||
|
||||
export type TIssuePeekOperations = {
|
||||
fetch: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
update: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
showToast?: boolean
|
||||
) => Promise<void>;
|
||||
update: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||
remove: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
archive: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
restore: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
@ -49,8 +44,6 @@ export type TIssuePeekOperations = {
|
||||
|
||||
export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
const { is_archived = false, is_draft = false } = props;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
// router
|
||||
const router = useRouter();
|
||||
const {
|
||||
@ -86,21 +79,9 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
console.error("Error fetching the parent issue");
|
||||
}
|
||||
},
|
||||
update: async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
showToast: boolean = true
|
||||
) => {
|
||||
try {
|
||||
await updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
if (showToast)
|
||||
setToastAlert({
|
||||
title: "Issue updated successfully",
|
||||
type: "success",
|
||||
message: "Issue updated successfully",
|
||||
});
|
||||
update: async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => {
|
||||
await updateIssue(workspaceSlug, projectId, issueId, data)
|
||||
.then(() => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...data, issueId, state: "SUCCESS", element: "Issue peek-overview" },
|
||||
@ -110,25 +91,26 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
})
|
||||
.catch(() => {
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { state: "FAILED", element: "Issue peek-overview" },
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue update failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Issue update failed",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
remove: async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
removeIssue(workspaceSlug, projectId, issueId);
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue deleted successfully",
|
||||
type: "success",
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
message: "Issue deleted successfully",
|
||||
});
|
||||
captureIssueEvent({
|
||||
@ -137,9 +119,9 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Issue delete failed",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: "Issue delete failed",
|
||||
});
|
||||
captureIssueEvent({
|
||||
@ -152,8 +134,8 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
archive: async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
await archiveIssue(workspaceSlug, projectId, issueId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Issue archived successfully.",
|
||||
});
|
||||
@ -163,8 +145,8 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issue could not be archived. Please try again.",
|
||||
});
|
||||
@ -178,8 +160,8 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
restore: async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
await restoreIssue(workspaceSlug, projectId, issueId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Issue restored successfully.",
|
||||
});
|
||||
@ -189,8 +171,8 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Issue could not be restored. Please try again.",
|
||||
});
|
||||
@ -203,12 +185,19 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
},
|
||||
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
||||
try {
|
||||
await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||
setToastAlert({
|
||||
title: "Cycle added to issue successfully",
|
||||
type: "success",
|
||||
message: "Issue added to issue successfully",
|
||||
const addToCyclePromise = addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||
setPromiseToast(addToCyclePromise, {
|
||||
loading: "Adding cycle to issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle added to issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Cycle add to issue failed",
|
||||
},
|
||||
});
|
||||
await addToCyclePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...issueIds, state: "SUCCESS", element: "Issue peek-overview" },
|
||||
@ -228,21 +217,23 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
title: "Cycle add to issue failed",
|
||||
type: "error",
|
||||
message: "Cycle add to issue failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
removeIssueFromCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||
setToastAlert({
|
||||
title: "Cycle removed from issue successfully",
|
||||
type: "success",
|
||||
message: "Cycle removed from issue successfully",
|
||||
const removeFromCyclePromise = removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||
setPromiseToast(removeFromCyclePromise, {
|
||||
loading: "Removing cycle from issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Cycle removed from issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Cycle remove from issue failed",
|
||||
},
|
||||
});
|
||||
const response = await removeFromCyclePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...response, state: "SUCCESS", element: "Issue peek-overview" },
|
||||
@ -253,11 +244,6 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
path: router.asPath,
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
title: "Cycle remove from issue failed",
|
||||
type: "error",
|
||||
message: "Cycle remove from issue failed",
|
||||
});
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { state: "FAILED", element: "Issue peek-overview" },
|
||||
@ -271,12 +257,19 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
},
|
||||
addModulesToIssue: async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||
try {
|
||||
const response = await addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setToastAlert({
|
||||
title: "Module added to issue successfully",
|
||||
type: "success",
|
||||
message: "Module added to issue successfully",
|
||||
const addToModulePromise = addModulesToIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setPromiseToast(addToModulePromise, {
|
||||
loading: "Adding module to issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Module added to issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Module add to issue failed",
|
||||
},
|
||||
});
|
||||
const response = await addToModulePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...response, state: "SUCCESS", element: "Issue peek-overview" },
|
||||
@ -296,21 +289,23 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
title: "Module add to issue failed",
|
||||
type: "error",
|
||||
message: "Module add to issue failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
removeIssueFromModule: async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => {
|
||||
try {
|
||||
await removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
||||
setToastAlert({
|
||||
title: "Module removed from issue successfully",
|
||||
type: "success",
|
||||
message: "Module removed from issue successfully",
|
||||
const removeFromModulePromise = removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
||||
setPromiseToast(removeFromModulePromise, {
|
||||
loading: "Removing module from issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Module removed from issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Module remove from issue failed",
|
||||
},
|
||||
});
|
||||
await removeFromModulePromise;
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
|
||||
@ -330,11 +325,6 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
title: "Module remove from issue failed",
|
||||
type: "error",
|
||||
message: "Module remove from issue failed",
|
||||
});
|
||||
}
|
||||
},
|
||||
removeModulesFromIssue: async (
|
||||
@ -343,20 +333,19 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
issueId: string,
|
||||
moduleIds: string[]
|
||||
) => {
|
||||
try {
|
||||
await removeModulesFromIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setToastAlert({
|
||||
title: "Module removed from issue successfully",
|
||||
type: "success",
|
||||
message: "Module removed from issue successfully",
|
||||
const removeModulesFromIssuePromise = removeModulesFromIssue(workspaceSlug, projectId, issueId, moduleIds);
|
||||
setPromiseToast(removeModulesFromIssuePromise, {
|
||||
loading: "Removing module from issue...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Module removed from issue successfully",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Module remove from issue failed",
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
title: "Module remove from issue failed",
|
||||
type: "error",
|
||||
message: "Module remove from issue failed",
|
||||
});
|
||||
}
|
||||
await removeModulesFromIssuePromise;
|
||||
},
|
||||
}),
|
||||
[
|
||||
@ -372,7 +361,6 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
addModulesToIssue,
|
||||
removeIssueFromModule,
|
||||
removeModulesFromIssue,
|
||||
setToastAlert,
|
||||
captureIssueEvent,
|
||||
router.asPath,
|
||||
]
|
||||
|
@ -5,7 +5,6 @@ import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
import useKeypress from "hooks/use-keypress";
|
||||
import useToast from "hooks/use-toast";
|
||||
// store hooks
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
// components
|
||||
@ -50,15 +49,13 @@ export const IssueView: FC<IIssueView> = observer((props) => {
|
||||
issue: { getIssueById },
|
||||
} = useIssueDetail();
|
||||
const issue = getIssueById(issueId);
|
||||
// hooks
|
||||
const { alerts } = useToast();
|
||||
// remove peek id
|
||||
const removeRoutePeekId = () => {
|
||||
setPeekIssue(undefined);
|
||||
};
|
||||
|
||||
useOutsideClickDetector(issuePeekOverviewRef, () => {
|
||||
if (!isAnyModalOpen && (!alerts || alerts.length === 0)) {
|
||||
if (!isAnyModalOpen) {
|
||||
removeRoutePeekId();
|
||||
}
|
||||
});
|
||||
|
@ -4,14 +4,13 @@ import { observer } from "mobx-react-lite";
|
||||
import { Plus, ChevronRight, ChevronDown, Loader } from "lucide-react";
|
||||
// hooks
|
||||
import { useEventTracker, useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { ExistingIssuesListModal } from "components/core";
|
||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
import { IssueList } from "./issues-list";
|
||||
import { ProgressBar } from "./progressbar";
|
||||
// ui
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
import { CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// helpers
|
||||
import { copyTextToClipboard } from "helpers/string.helper";
|
||||
// types
|
||||
@ -46,8 +45,6 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
const { workspaceSlug, projectId, parentIssueId, disabled = false } = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
// store hooks
|
||||
const { setToastAlert } = useToast();
|
||||
const {
|
||||
issue: { getIssueById },
|
||||
subIssues: { subIssuesByIssueId, stateDistributionByIssueId, subIssueHelpersByIssueId, setSubIssueHelpers },
|
||||
@ -128,8 +125,8 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
copyText: (text: string) => {
|
||||
const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
|
||||
copyTextToClipboard(`${originURL}/${text}`).then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Link Copied!",
|
||||
message: "Issue link copied to clipboard.",
|
||||
});
|
||||
@ -139,8 +136,8 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
try {
|
||||
await fetchSubIssues(workspaceSlug, projectId, parentIssueId);
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error fetching sub-issues",
|
||||
message: "Error fetching sub-issues",
|
||||
});
|
||||
@ -149,14 +146,14 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
addSubIssue: async (workspaceSlug: string, projectId: string, parentIssueId: string, issueIds: string[]) => {
|
||||
try {
|
||||
await createSubIssues(workspaceSlug, projectId, parentIssueId, issueIds);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Sub-issues added successfully",
|
||||
message: "Sub-issues added successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error adding sub-issue",
|
||||
message: "Error adding sub-issue",
|
||||
});
|
||||
@ -183,8 +180,8 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Sub-issue updated successfully",
|
||||
message: "Sub-issue updated successfully",
|
||||
});
|
||||
@ -199,8 +196,8 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error updating sub-issue",
|
||||
message: "Error updating sub-issue",
|
||||
});
|
||||
@ -210,8 +207,8 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
try {
|
||||
setSubIssueHelpers(parentIssueId, "issue_loader", issueId);
|
||||
await removeSubIssue(workspaceSlug, projectId, parentIssueId, issueId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Sub-issue removed successfully",
|
||||
message: "Sub-issue removed successfully",
|
||||
});
|
||||
@ -235,8 +232,8 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
},
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error removing sub-issue",
|
||||
message: "Error removing sub-issue",
|
||||
});
|
||||
@ -246,8 +243,8 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
try {
|
||||
setSubIssueHelpers(parentIssueId, "issue_loader", issueId);
|
||||
await deleteSubIssue(workspaceSlug, projectId, parentIssueId, issueId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Issue deleted successfully",
|
||||
message: "Issue deleted successfully",
|
||||
});
|
||||
@ -263,15 +260,15 @@ export const SubIssuesRoot: FC<ISubIssuesRoot> = observer((props) => {
|
||||
payload: { id: issueId, state: "FAILED", element: "Issue detail page" },
|
||||
path: router.asPath,
|
||||
});
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error deleting issue",
|
||||
message: "Error deleting issue",
|
||||
});
|
||||
}
|
||||
},
|
||||
}),
|
||||
[fetchSubIssues, createSubIssues, updateSubIssue, removeSubIssue, deleteSubIssue, setToastAlert, setSubIssueHelpers]
|
||||
[fetchSubIssues, createSubIssues, updateSubIssue, removeSubIssue, deleteSubIssue, setSubIssueHelpers]
|
||||
);
|
||||
|
||||
const issue = getIssueById(parentIssueId);
|
||||
|
@ -32,7 +32,7 @@ export const IssueTitleInput: FC<IssueTitleInputProps> = observer((props) => {
|
||||
useEffect(() => {
|
||||
const textarea = document.querySelector("#title-input");
|
||||
if (debouncedValue && debouncedValue !== value) {
|
||||
issueOperations.update(workspaceSlug, projectId, issueId, { name: debouncedValue }, false).finally(() => {
|
||||
issueOperations.update(workspaceSlug, projectId, issueId, { name: debouncedValue }).finally(() => {
|
||||
setIsSubmitting("saved");
|
||||
if (textarea && !textarea.matches(":focus")) {
|
||||
const trimmedTitle = debouncedValue.trim();
|
||||
|
@ -7,9 +7,8 @@ import { Dialog, Popover, Transition } from "@headlessui/react";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
// hooks
|
||||
import { useLabel } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { Button, Input } from "@plane/ui";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// types
|
||||
import type { IIssueLabel, IState } from "@plane/types";
|
||||
// constants
|
||||
@ -64,8 +63,6 @@ export const CreateLabelModal: React.FC<Props> = observer((props) => {
|
||||
reset(defaultValues);
|
||||
};
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const onSubmit = async (formData: IIssueLabel) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
@ -75,9 +72,9 @@ export const CreateLabelModal: React.FC<Props> = observer((props) => {
|
||||
if (onSuccess) onSuccess(res);
|
||||
})
|
||||
.catch((error) => {
|
||||
setToastAlert({
|
||||
setToast({
|
||||
title: "Oops!",
|
||||
type: "error",
|
||||
type: TOAST_TYPE.ERROR,
|
||||
message: error?.error ?? "Error while adding the label",
|
||||
});
|
||||
reset(formData);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user