UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: приведение delete-модалок к black-glass канону
This commit is contained in:
parent
cbd40791e4
commit
6cb0545957
|
|
@ -49,8 +49,8 @@ export const CycleDeleteModal = observer(function CycleDeleteModal(props: ICycle
|
||||||
if (cycleId || peekCycle) router.push(`/${workspaceSlug}/projects/${projectId}/cycles`);
|
if (cycleId || peekCycle) router.push(`/${workspaceSlug}/projects/${projectId}/cycles`);
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Success!",
|
title: t("common.success"),
|
||||||
message: "Cycle deleted successfully.",
|
message: t("entity.delete.success", { entity: t("common.cycle").toLowerCase() }),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((errors) => {
|
.catch((errors) => {
|
||||||
|
|
@ -68,8 +68,8 @@ export const CycleDeleteModal = observer(function CycleDeleteModal(props: ICycle
|
||||||
} catch {
|
} catch {
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Warning!",
|
title: t("common.warning"),
|
||||||
message: "Something went wrong please try again later.",
|
message: t("common.something_went_wrong"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,14 +82,11 @@ export const CycleDeleteModal = observer(function CycleDeleteModal(props: ICycle
|
||||||
handleSubmit={formSubmit}
|
handleSubmit={formSubmit}
|
||||||
isSubmitting={loader}
|
isSubmitting={loader}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title="Delete cycle"
|
title={t("entity.delete.label", { entity: t("common.cycle") })}
|
||||||
content={
|
content={t("entity.delete.confirmation", {
|
||||||
<>
|
entity: t("common.cycle").toLowerCase(),
|
||||||
Are you sure you want to delete cycle{' "'}
|
identifier: cycle?.name ? `"${cycle.name}"` : "",
|
||||||
<span className="font-medium break-words text-primary">{cycle?.name}</span>
|
})}
|
||||||
{'"'}? All of the data related to the cycle will be permanently removed. This action cannot be undone.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
// ui
|
// ui
|
||||||
import { Button } from "@plane/propel/button";
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||||
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
|
import { AlertModalCore } from "@plane/ui";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProjectEstimates } from "@/hooks/store/estimates";
|
import { useProjectEstimates } from "@/hooks/store/estimates";
|
||||||
import { useEstimate } from "@/hooks/store/estimates/use-estimate";
|
import { useEstimate } from "@/hooks/store/estimates/use-estimate";
|
||||||
|
|
@ -26,6 +26,7 @@ type TDeleteEstimateModal = {
|
||||||
export const DeleteEstimateModal = observer(function DeleteEstimateModal(props: TDeleteEstimateModal) {
|
export const DeleteEstimateModal = observer(function DeleteEstimateModal(props: TDeleteEstimateModal) {
|
||||||
// props
|
// props
|
||||||
const { workspaceSlug, projectId, estimateId, isOpen, handleClose } = props;
|
const { workspaceSlug, projectId, estimateId, isOpen, handleClose } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
// hooks
|
// hooks
|
||||||
const { areEstimateEnabledByProjectId, deleteEstimate } = useProjectEstimates();
|
const { areEstimateEnabledByProjectId, deleteEstimate } = useProjectEstimates();
|
||||||
const { asJson: estimate } = useEstimate(estimateId);
|
const { asJson: estimate } = useEstimate(estimateId);
|
||||||
|
|
@ -44,46 +45,32 @@ export const DeleteEstimateModal = observer(function DeleteEstimateModal(props:
|
||||||
setButtonLoader(false);
|
setButtonLoader(false);
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Estimate deleted",
|
title: t("project_settings.estimates.delete_modal.success_title"),
|
||||||
message: "Estimate has been removed from your project.",
|
message: t("project_settings.estimates.delete_modal.success_message"),
|
||||||
});
|
});
|
||||||
handleClose();
|
handleClose();
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
setButtonLoader(false);
|
setButtonLoader(false);
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Estimate creation failed",
|
title: t("project_settings.estimates.delete_modal.error_title"),
|
||||||
message: "We were unable to delete the estimate, please try again.",
|
message: t("project_settings.estimates.delete_modal.error_message"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalCore isOpen={isOpen} position={EModalPosition.TOP} width={EModalWidth.XXL}>
|
<AlertModalCore
|
||||||
<div className="relative space-y-6 py-5">
|
handleClose={handleClose}
|
||||||
{/* heading */}
|
handleSubmit={handleDeleteEstimate}
|
||||||
<div className="relative flex items-center justify-between gap-2 px-5">
|
isSubmitting={buttonLoader}
|
||||||
<div className="text-18 font-medium text-primary">Delete Estimate System</div>
|
isOpen={isOpen}
|
||||||
</div>
|
title={t("project_settings.estimates.delete_modal.title")}
|
||||||
|
content={t("project_settings.estimates.delete_modal.description", { value: estimate?.name ?? "" })}
|
||||||
{/* estimate steps */}
|
primaryButtonText={{
|
||||||
<div className="px-5">
|
loading: t("project_settings.estimates.delete_modal.loading"),
|
||||||
<div className="text-14 text-secondary">
|
default: t("project_settings.estimates.delete_modal.submit"),
|
||||||
Deleting the estimate <span className="font-bold text-primary">{estimate?.name}</span>
|
}}
|
||||||
system will remove it from all work items permanently. This action cannot be undone. If you add
|
/>
|
||||||
estimates again, you will need to update all the work items.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="relative flex items-center justify-end gap-3 border-t border-subtle px-5 pt-5">
|
|
||||||
<Button variant="secondary" size="lg" onClick={handleClose} disabled={buttonLoader}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button variant="error-fill" size="lg" onClick={handleDeleteEstimate} disabled={buttonLoader}>
|
|
||||||
{buttonLoader ? "Deleting" : "Delete Estimate"}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ModalCore>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -47,16 +47,9 @@ export function DeclineIssueModal(props: Props) {
|
||||||
isSubmitting={isDeclining}
|
isSubmitting={isDeclining}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title={t("inbox_issue.modals.decline.title")}
|
title={t("inbox_issue.modals.decline.title")}
|
||||||
// TODO: Need to translate the confirmation message
|
content={t("inbox_issue.modals.decline.content", {
|
||||||
content={
|
value: `${projectDetails?.identifier}-${data?.sequence_id}`,
|
||||||
<>
|
})}
|
||||||
Are you sure you want to decline work item{" "}
|
|
||||||
<span className="font-medium break-words text-primary">
|
|
||||||
{projectDetails?.identifier}-{data?.sequence_id}
|
|
||||||
</span>
|
|
||||||
{""}? This action cannot be undone.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
primaryButtonText={{
|
primaryButtonText={{
|
||||||
loading: t("declining"),
|
loading: t("declining"),
|
||||||
default: t("decline"),
|
default: t("decline"),
|
||||||
|
|
|
||||||
|
|
@ -63,14 +63,7 @@ export const IssueAttachmentDeleteModal = observer(function IssueAttachmentDelet
|
||||||
isSubmitting={loader}
|
isSubmitting={loader}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title={t("attachment.delete")}
|
title={t("attachment.delete")}
|
||||||
content={
|
content={t("attachment.delete_confirmation", { value: getFileName(attachment.attributes.name) })}
|
||||||
<>
|
|
||||||
{/* TODO: Translate here */}
|
|
||||||
Are you sure you want to delete attachment-{" "}
|
|
||||||
<span className="font-bold">{getFileName(attachment.attributes.name)}</span>? This attachment will be
|
|
||||||
permanently removed. This action cannot be undone.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { useState } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// types
|
// types
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||||
import type { IIssueLabel } from "@plane/types";
|
import type { IIssueLabel } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
|
|
@ -23,6 +24,7 @@ type Props = {
|
||||||
|
|
||||||
export const DeleteLabelModal = observer(function DeleteLabelModal(props: Props) {
|
export const DeleteLabelModal = observer(function DeleteLabelModal(props: Props) {
|
||||||
const { isOpen, onClose, data } = props;
|
const { isOpen, onClose, data } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
// router
|
// router
|
||||||
const { workspaceSlug, projectId } = useParams();
|
const { workspaceSlug, projectId } = useParams();
|
||||||
// store hooks
|
// store hooks
|
||||||
|
|
@ -46,10 +48,10 @@ export const DeleteLabelModal = observer(function DeleteLabelModal(props: Props)
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setIsDeleteLoading(false);
|
setIsDeleteLoading(false);
|
||||||
const error = err?.error || "Label could not be deleted. Please try again.";
|
const error = err?.error || t("label.delete_error");
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Error!",
|
title: t("common.error.label"),
|
||||||
message: error,
|
message: error,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -61,13 +63,8 @@ export const DeleteLabelModal = observer(function DeleteLabelModal(props: Props)
|
||||||
handleSubmit={handleDeletion}
|
handleSubmit={handleDeletion}
|
||||||
isSubmitting={isDeleteLoading}
|
isSubmitting={isDeleteLoading}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title="Delete Label"
|
title={t("entity.delete.label", { entity: t("common.label") })}
|
||||||
content={
|
content={t("label.delete_confirmation", { value: data?.name ?? "" })}
|
||||||
<>
|
|
||||||
Are you sure you want to delete <span className="font-medium text-primary">{data?.name}</span>? This will
|
|
||||||
remove the label from all the work item and from any views where the label is being filtered upon.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ export const DeleteModuleModal = observer(function DeleteModuleModal(props: Prop
|
||||||
handleClose();
|
handleClose();
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Success!",
|
title: t("common.success"),
|
||||||
message: "Module deleted successfully.",
|
message: t("entity.delete.success", { entity: t("common.module").toLowerCase() }),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((errors) => {
|
.catch((errors) => {
|
||||||
|
|
@ -76,14 +76,11 @@ export const DeleteModuleModal = observer(function DeleteModuleModal(props: Prop
|
||||||
handleSubmit={handleDeletion}
|
handleSubmit={handleDeletion}
|
||||||
isSubmitting={isDeleteLoading}
|
isSubmitting={isDeleteLoading}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title="Delete module"
|
title={t("entity.delete.label", { entity: t("common.module") })}
|
||||||
content={
|
content={t("entity.delete.confirmation", {
|
||||||
<>
|
entity: t("common.module").toLowerCase(),
|
||||||
Are you sure you want to delete module-{" "}
|
identifier: data?.name ? `"${data.name}"` : "",
|
||||||
<span className="font-medium break-all text-primary">{data?.name}</span>? All of the data related to the
|
})}
|
||||||
module will be permanently removed. This action cannot be undone.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { useState } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
// ui
|
// ui
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||||
import { AlertModalCore } from "@plane/ui";
|
import { AlertModalCore } from "@plane/ui";
|
||||||
import { getPageName } from "@plane/utils";
|
import { getPageName } from "@plane/utils";
|
||||||
|
|
@ -28,6 +29,7 @@ type TConfirmPageDeletionProps = {
|
||||||
|
|
||||||
export const DeletePageModal = observer(function DeletePageModal(props: TConfirmPageDeletionProps) {
|
export const DeletePageModal = observer(function DeletePageModal(props: TConfirmPageDeletionProps) {
|
||||||
const { isOpen, onClose, page, storeType } = props;
|
const { isOpen, onClose, page, storeType } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
// states
|
// states
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
// store hooks
|
// store hooks
|
||||||
|
|
@ -52,8 +54,8 @@ export const DeletePageModal = observer(function DeletePageModal(props: TConfirm
|
||||||
handleClose();
|
handleClose();
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Success!",
|
title: t("project_page.delete_modal.success_title"),
|
||||||
message: "Page deleted successfully.",
|
message: t("project_page.delete_modal.success_message"),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (routePageId) {
|
if (routePageId) {
|
||||||
|
|
@ -63,8 +65,8 @@ export const DeletePageModal = observer(function DeletePageModal(props: TConfirm
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Error!",
|
title: t("project_page.delete_modal.error_title"),
|
||||||
message: "Page could not be deleted. Please try again.",
|
message: t("project_page.delete_modal.error_message"),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -79,14 +81,8 @@ export const DeletePageModal = observer(function DeletePageModal(props: TConfirm
|
||||||
handleSubmit={handleDelete}
|
handleSubmit={handleDelete}
|
||||||
isSubmitting={isDeleting}
|
isSubmitting={isDeleting}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title="Delete page"
|
title={t("project_page.delete_modal.title")}
|
||||||
content={
|
content={t("project_page.delete_modal.content", { value: getPageName(name) })}
|
||||||
<>
|
|
||||||
Are you sure you want to delete page-{" "}
|
|
||||||
<span className="font-medium break-words break-all text-primary">{getPageName(name)}</span> ? The Page will be
|
|
||||||
deleted permanently. This action cannot be undone.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Loader } from "lucide-react";
|
import { Loader } from "lucide-react";
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { CloseIcon } from "@plane/propel/icons";
|
import { CloseIcon } from "@plane/propel/icons";
|
||||||
// plane imports
|
// plane imports
|
||||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||||
|
|
@ -26,6 +27,7 @@ type TStateDelete = {
|
||||||
|
|
||||||
export const StateDelete = observer(function StateDelete(props: TStateDelete) {
|
export const StateDelete = observer(function StateDelete(props: TStateDelete) {
|
||||||
const { totalStates, state, deleteStateCallback } = props;
|
const { totalStates, state, deleteStateCallback } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
// hooks
|
// hooks
|
||||||
const { isMobile } = usePlatformOS();
|
const { isMobile } = usePlatformOS();
|
||||||
// states
|
// states
|
||||||
|
|
@ -47,15 +49,14 @@ export const StateDelete = observer(function StateDelete(props: TStateDelete) {
|
||||||
if (errorStatus.status === 400) {
|
if (errorStatus.status === 400) {
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Error!",
|
title: t("common.error.label"),
|
||||||
message:
|
message: t("project_settings.states.delete.blocked"),
|
||||||
"This state contains some work items within it, please move them to some other state to delete this state.",
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Error!",
|
title: t("common.error.label"),
|
||||||
message: "State could not be deleted. Please try again.",
|
message: t("project_settings.states.delete.error"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setIsDelete(false);
|
setIsDelete(false);
|
||||||
|
|
@ -69,13 +70,11 @@ export const StateDelete = observer(function StateDelete(props: TStateDelete) {
|
||||||
handleSubmit={handleDeleteState}
|
handleSubmit={handleDeleteState}
|
||||||
isSubmitting={isDelete}
|
isSubmitting={isDelete}
|
||||||
isOpen={isDeleteModal}
|
isOpen={isDeleteModal}
|
||||||
title="Delete State"
|
title={t("entity.delete.label", { entity: t("common.state") })}
|
||||||
content={
|
content={t("entity.delete.confirmation", {
|
||||||
<>
|
entity: t("common.state").toLowerCase(),
|
||||||
Are you sure you want to delete state- <span className="font-medium text-primary">{state?.name}</span>? All
|
identifier: state?.name ? `"${state.name}"` : "",
|
||||||
of the data related to the state will be permanently removed. This action cannot be undone.
|
})}
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|
@ -89,7 +88,11 @@ export const StateDelete = observer(function StateDelete(props: TStateDelete) {
|
||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
tooltipContent={
|
tooltipContent={
|
||||||
state.default ? "Cannot delete the default state." : totalStates === 1 ? `Cannot have an empty group.` : ``
|
state.default
|
||||||
|
? t("project_settings.states.delete.disabled_default")
|
||||||
|
: totalStates === 1
|
||||||
|
? t("project_settings.states.delete.disabled_last")
|
||||||
|
: ""
|
||||||
}
|
}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
disabled={!isDeleteDisabled}
|
disabled={!isDeleteDisabled}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { useState } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// Plane imports
|
// Plane imports
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||||
import type { IState } from "@plane/types";
|
import type { IState } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
|
|
@ -23,6 +24,7 @@ type TStateDeleteModal = {
|
||||||
|
|
||||||
export const StateDeleteModal = observer(function StateDeleteModal(props: TStateDeleteModal) {
|
export const StateDeleteModal = observer(function StateDeleteModal(props: TStateDeleteModal) {
|
||||||
const { isOpen, onClose, data } = props;
|
const { isOpen, onClose, data } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
// states
|
// states
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
// router
|
// router
|
||||||
|
|
@ -47,15 +49,14 @@ export const StateDeleteModal = observer(function StateDeleteModal(props: TState
|
||||||
if (err.status === 400)
|
if (err.status === 400)
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Error!",
|
title: t("common.error.label"),
|
||||||
message:
|
message: t("project_settings.states.delete.blocked"),
|
||||||
"This state contains some work items within it, please move them to some other state to delete this state.",
|
|
||||||
});
|
});
|
||||||
else
|
else
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Error!",
|
title: t("common.error.label"),
|
||||||
message: "State could not be deleted. Please try again.",
|
message: t("project_settings.states.delete.error"),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|
@ -69,13 +70,11 @@ export const StateDeleteModal = observer(function StateDeleteModal(props: TState
|
||||||
handleSubmit={handleDeletion}
|
handleSubmit={handleDeletion}
|
||||||
isSubmitting={isDeleteLoading}
|
isSubmitting={isDeleteLoading}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title="Delete State"
|
title={t("entity.delete.label", { entity: t("common.state") })}
|
||||||
content={
|
content={t("entity.delete.confirmation", {
|
||||||
<>
|
entity: t("common.state").toLowerCase(),
|
||||||
Are you sure you want to delete state- <span className="font-medium text-primary">{data?.name}</span>? All of
|
identifier: data?.name ? `"${data.name}"` : "",
|
||||||
the data related to the state will be permanently removed. This action cannot be undone.
|
})}
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// ui
|
// ui
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||||
import { AlertModalCore } from "@plane/ui";
|
import { AlertModalCore } from "@plane/ui";
|
||||||
// hooks
|
// hooks
|
||||||
|
|
@ -20,6 +21,7 @@ interface IDeleteWebhook {
|
||||||
|
|
||||||
export function DeleteWebhookModal(props: IDeleteWebhook) {
|
export function DeleteWebhookModal(props: IDeleteWebhook) {
|
||||||
const { isOpen, onClose } = props;
|
const { isOpen, onClose } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
// states
|
// states
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
// router
|
// router
|
||||||
|
|
@ -41,14 +43,14 @@ export function DeleteWebhookModal(props: IDeleteWebhook) {
|
||||||
router.replace(`/${workspaceSlug}/settings/webhooks/`);
|
router.replace(`/${workspaceSlug}/settings/webhooks/`);
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Success!",
|
title: t("workspace_settings.settings.webhooks.toasts.removed.title"),
|
||||||
message: "Webhook deleted successfully.",
|
message: t("workspace_settings.settings.webhooks.toasts.removed.message"),
|
||||||
});
|
});
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "Error!",
|
title: t("workspace_settings.settings.webhooks.toasts.not_removed.title"),
|
||||||
message: "Webhook could not be deleted. Please try again.",
|
message: t("workspace_settings.settings.webhooks.toasts.not_removed.message"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setIsDeleting(false);
|
setIsDeleting(false);
|
||||||
|
|
@ -60,13 +62,8 @@ export function DeleteWebhookModal(props: IDeleteWebhook) {
|
||||||
handleSubmit={handleDelete}
|
handleSubmit={handleDelete}
|
||||||
isSubmitting={isDeleting}
|
isSubmitting={isDeleting}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
title="Delete webhook"
|
title={t("workspace_settings.settings.webhooks.delete.title")}
|
||||||
content={
|
content={t("workspace_settings.settings.webhooks.delete.description")}
|
||||||
<>
|
|
||||||
Are you sure you want to delete this webhook? Future events will not be delivered to this webhook. This action
|
|
||||||
cannot be undone.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import { Disclosure, Transition } from "@headlessui/react";
|
import { Disclosure, Transition } from "@headlessui/react";
|
||||||
import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
|
import { WORKSPACE_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { Button } from "@plane/propel/button";
|
import { Button } from "@plane/propel/button";
|
||||||
import { ChevronDownIcon, ChevronUpIcon } from "@plane/propel/icons";
|
import { ChevronDownIcon, ChevronUpIcon } from "@plane/propel/icons";
|
||||||
|
|
||||||
|
|
@ -15,13 +16,14 @@ type Props = {
|
||||||
|
|
||||||
export function WebhookDeleteSection(props: Props) {
|
export function WebhookDeleteSection(props: Props) {
|
||||||
const { openDeleteModal } = props;
|
const { openDeleteModal } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Disclosure as="div" className="border-t border-subtle">
|
<Disclosure as="div" className="border-t border-subtle">
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Disclosure.Button as="button" type="button" className="flex w-full items-center justify-between py-4">
|
<Disclosure.Button as="button" type="button" className="flex w-full items-center justify-between py-4">
|
||||||
<span className="text-16 tracking-tight">Danger zone</span>
|
<span className="text-16 tracking-tight">{t("workspace_settings.settings.webhooks.delete.title")}</span>
|
||||||
{open ? <ChevronUpIcon className="h-5 w-5" /> : <ChevronDownIcon className="h-5 w-5" />}
|
{open ? <ChevronUpIcon className="h-5 w-5" /> : <ChevronDownIcon className="h-5 w-5" />}
|
||||||
</Disclosure.Button>
|
</Disclosure.Button>
|
||||||
|
|
||||||
|
|
@ -36,18 +38,16 @@ export function WebhookDeleteSection(props: Props) {
|
||||||
>
|
>
|
||||||
<Disclosure.Panel>
|
<Disclosure.Panel>
|
||||||
<div className="flex flex-col gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
<span className="text-13 tracking-tight">
|
<span className="text-13 tracking-tight">{t("workspace_settings.settings.webhooks.delete.description")}</span>
|
||||||
Once a webhook is deleted, it cannot be restored. Future events will no longer be delivered to this
|
|
||||||
webhook.
|
|
||||||
</span>
|
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
variant="error-fill"
|
variant="error-fill"
|
||||||
size="lg"
|
size="lg"
|
||||||
onClick={openDeleteModal}
|
onClick={openDeleteModal}
|
||||||
|
className="nodedc-modal-danger-button"
|
||||||
data-ph-element={WORKSPACE_SETTINGS_TRACKER_ELEMENTS.WEBHOOK_DELETE_BUTTON}
|
data-ph-element={WORKSPACE_SETTINGS_TRACKER_ELEMENTS.WEBHOOK_DELETE_BUTTON}
|
||||||
>
|
>
|
||||||
Delete webhook
|
{t("workspace_settings.settings.webhooks.delete.title")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -218,9 +218,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-glass-modal {
|
.nodedc-glass-modal {
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.036) 0%, rgba(255, 255, 255, 0.012) 100%),
|
||||||
|
rgba(6, 6, 8, 0.9) !important;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
-webkit-backdrop-filter: blur(42px);
|
||||||
|
backdrop-filter: blur(42px);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 20px 56px rgba(0, 0, 0, 0.34),
|
0 24px 64px rgba(0, 0, 0, 0.42),
|
||||||
0 4px 16px rgba(0, 0, 0, 0.18);
|
0 8px 22px rgba(0, 0, 0, 0.24);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-glass-surface {
|
.nodedc-glass-surface {
|
||||||
|
|
@ -268,11 +275,24 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-glass-modal button:focus-visible,
|
.nodedc-glass-modal button:focus-visible,
|
||||||
.nodedc-glass-modal [role="button"]:focus-visible {
|
.nodedc-glass-modal [role="button"]:focus-visible,
|
||||||
|
.nodedc-glass-modal :focus-visible {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nodedc-modal-alert-icon {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-modal-alert-icon-danger,
|
||||||
|
.nodedc-modal-alert-icon-primary {
|
||||||
|
background: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 18%, transparent) !important;
|
||||||
|
color: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.nodedc-modal-field {
|
.nodedc-modal-field {
|
||||||
background:
|
background:
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, rgba(255, 255, 255, 0.012) 100%),
|
linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, rgba(255, 255, 255, 0.012) 100%),
|
||||||
|
|
@ -485,17 +505,19 @@
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
border-radius: 1.25rem !important;
|
border-radius: 1.25rem !important;
|
||||||
background: rgb(var(--nodedc-card-active-rgb)) !important;
|
background: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
color: #0b1117 !important;
|
color: #0b1117 !important;
|
||||||
padding-inline: 1.25rem !important;
|
padding-inline: 1.25rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-modal-primary-button:hover {
|
.nodedc-modal-primary-button:hover {
|
||||||
background: color-mix(in srgb, rgb(var(--nodedc-card-active-rgb)) 82%, white) !important;
|
background: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 82%, white) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodedc-modal-primary-button,
|
.nodedc-modal-primary-button,
|
||||||
.nodedc-modal-primary-button *,
|
.nodedc-modal-primary-button *,
|
||||||
|
.nodedc-modal-danger-button,
|
||||||
|
.nodedc-modal-danger-button *,
|
||||||
.nodedc-settings-primary-button,
|
.nodedc-settings-primary-button,
|
||||||
.nodedc-settings-primary-button *,
|
.nodedc-settings-primary-button *,
|
||||||
.nodedc-settings-save-button,
|
.nodedc-settings-save-button,
|
||||||
|
|
@ -509,9 +531,34 @@
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
border-radius: 1.25rem !important;
|
border-radius: 1.25rem !important;
|
||||||
|
background: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
padding-inline: 1.25rem !important;
|
padding-inline: 1.25rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nodedc-modal-danger-button:hover {
|
||||||
|
background: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 82%, white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-glass-modal button.bg-danger-primary,
|
||||||
|
.nodedc-glass-modal button.border-danger-strong {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
background: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-glass-modal button.bg-danger-primary:hover,
|
||||||
|
.nodedc-glass-modal button.border-danger-strong:hover {
|
||||||
|
background: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 82%, white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-glass-modal button.bg-danger-primary *,
|
||||||
|
.nodedc-glass-modal button.border-danger-strong * {
|
||||||
|
color: #0b1117 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.nodedc-modal-chip {
|
.nodedc-modal-chip {
|
||||||
min-height: 2.5rem;
|
min-height: 2.5rem;
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
|
|
|
||||||
|
|
@ -1138,9 +1138,14 @@ export default {
|
||||||
file_size_limit: "File must be of {size}MB or less in size.",
|
file_size_limit: "File must be of {size}MB or less in size.",
|
||||||
drag_and_drop: "Drag and drop anywhere to upload",
|
drag_and_drop: "Drag and drop anywhere to upload",
|
||||||
delete: "Delete attachment",
|
delete: "Delete attachment",
|
||||||
|
delete_confirmation:
|
||||||
|
"Are you sure you want to delete attachment {value}? This attachment will be permanently removed and this action cannot be undone.",
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
select: "Add labels",
|
select: "Add labels",
|
||||||
|
delete_confirmation:
|
||||||
|
'Are you sure you want to delete label "{value}"? It will be removed from all work items and from any views where this label is used.',
|
||||||
|
delete_error: "Label could not be deleted. Please try again.",
|
||||||
create: {
|
create: {
|
||||||
success: "Label created successfully",
|
success: "Label created successfully",
|
||||||
failed: "Label creation failed",
|
failed: "Label creation failed",
|
||||||
|
|
@ -1205,7 +1210,7 @@ export default {
|
||||||
modals: {
|
modals: {
|
||||||
decline: {
|
decline: {
|
||||||
title: "Decline work item",
|
title: "Decline work item",
|
||||||
content: "Are you sure you want to decline work item {value}?",
|
content: "Are you sure you want to decline work item {value}? This action cannot be undone.",
|
||||||
},
|
},
|
||||||
delete: {
|
delete: {
|
||||||
title: "Delete work item",
|
title: "Delete work item",
|
||||||
|
|
@ -1691,6 +1696,11 @@ export default {
|
||||||
description: "Automate notifications to external services when project events occur.",
|
description: "Automate notifications to external services when project events occur.",
|
||||||
title: "Webhooks",
|
title: "Webhooks",
|
||||||
add_webhook: "Add webhook",
|
add_webhook: "Add webhook",
|
||||||
|
delete: {
|
||||||
|
title: "Delete webhook",
|
||||||
|
description:
|
||||||
|
"Are you sure you want to delete this webhook? Future events will no longer be delivered to it. This action cannot be undone.",
|
||||||
|
},
|
||||||
modal: {
|
modal: {
|
||||||
title: "Create webhook",
|
title: "Create webhook",
|
||||||
details: "Webhook details",
|
details: "Webhook details",
|
||||||
|
|
@ -1886,6 +1896,12 @@ export default {
|
||||||
heading: "States",
|
heading: "States",
|
||||||
description: "Define and customize workflow states to track the progress of your work items.",
|
description: "Define and customize workflow states to track the progress of your work items.",
|
||||||
describe_this_state_for_your_members: "Describe this state for your members.",
|
describe_this_state_for_your_members: "Describe this state for your members.",
|
||||||
|
delete: {
|
||||||
|
blocked: "This state still contains work items. Move them to another state before deleting it.",
|
||||||
|
error: "State could not be deleted. Please try again.",
|
||||||
|
disabled_default: "Cannot delete the default state.",
|
||||||
|
disabled_last: "Cannot leave the group without states.",
|
||||||
|
},
|
||||||
empty_state: {
|
empty_state: {
|
||||||
title: "No states available for the {groupKey} group",
|
title: "No states available for the {groupKey} group",
|
||||||
description: "Please create a new state",
|
description: "Please create a new state",
|
||||||
|
|
@ -1914,6 +1930,17 @@ export default {
|
||||||
label: "Estimates",
|
label: "Estimates",
|
||||||
title: "Enable estimates for my project",
|
title: "Enable estimates for my project",
|
||||||
enable_description: "They help you in communicating complexity and workload of the team.",
|
enable_description: "They help you in communicating complexity and workload of the team.",
|
||||||
|
delete_modal: {
|
||||||
|
title: "Delete estimate system",
|
||||||
|
description:
|
||||||
|
'Deleting the estimate system "{value}" will permanently remove it from every work item in this project. If you enable estimates again later, you will need to configure work items again.',
|
||||||
|
submit: "Delete estimate system",
|
||||||
|
loading: "Deleting",
|
||||||
|
success_title: "Estimate system deleted",
|
||||||
|
success_message: "The estimate system has been removed from the project.",
|
||||||
|
error_title: "Estimate system delete failed",
|
||||||
|
error_message: "We were unable to delete the estimate system. Please try again.",
|
||||||
|
},
|
||||||
list_heading: "Estimate list",
|
list_heading: "Estimate list",
|
||||||
archived_heading: "Archived estimates",
|
archived_heading: "Archived estimates",
|
||||||
archived_description: "These are estimates from earlier project versions that are not currently in use. Read more",
|
archived_description: "These are estimates from earlier project versions that are not currently in use. Read more",
|
||||||
|
|
@ -2304,6 +2331,14 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
project_page: {
|
project_page: {
|
||||||
|
delete_modal: {
|
||||||
|
title: "Delete page",
|
||||||
|
content: 'Are you sure you want to delete page "{value}"? The page will be permanently removed and this action cannot be undone.',
|
||||||
|
success_title: "Page deleted",
|
||||||
|
success_message: "Page deleted successfully.",
|
||||||
|
error_title: "Page delete failed",
|
||||||
|
error_message: "Page could not be deleted. Please try again.",
|
||||||
|
},
|
||||||
empty_state: {
|
empty_state: {
|
||||||
general: {
|
general: {
|
||||||
title:
|
title:
|
||||||
|
|
|
||||||
|
|
@ -1294,9 +1294,14 @@ export default {
|
||||||
file_size_limit: "Максимальный размер файла - {size} МБ",
|
file_size_limit: "Максимальный размер файла - {size} МБ",
|
||||||
drag_and_drop: "Перетащите файл для загрузки",
|
drag_and_drop: "Перетащите файл для загрузки",
|
||||||
delete: "Удалить вложение",
|
delete: "Удалить вложение",
|
||||||
|
delete_confirmation:
|
||||||
|
"Вы уверены, что хотите удалить вложение {value}? Вложение будет удалено без возможности восстановления.",
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
select: "Выбрать метку",
|
select: "Выбрать метку",
|
||||||
|
delete_confirmation:
|
||||||
|
'Вы уверены, что хотите удалить метку "{value}"? Она будет удалена из всех рабочих элементов и представлений, где используется.',
|
||||||
|
delete_error: "Не удалось удалить метку. Попробуйте снова.",
|
||||||
create: {
|
create: {
|
||||||
success: "Метка создана",
|
success: "Метка создана",
|
||||||
failed: "Ошибка создания метки",
|
failed: "Ошибка создания метки",
|
||||||
|
|
@ -1361,7 +1366,7 @@ export default {
|
||||||
modals: {
|
modals: {
|
||||||
decline: {
|
decline: {
|
||||||
title: "Отклонить рабочий элемент",
|
title: "Отклонить рабочий элемент",
|
||||||
content: "Вы уверены, что хотите отклонить рабочий элемент {value}?",
|
content: "Вы уверены, что хотите отклонить рабочий элемент {value}? Это действие нельзя отменить.",
|
||||||
},
|
},
|
||||||
delete: {
|
delete: {
|
||||||
title: "Удалить рабочий элемент",
|
title: "Удалить рабочий элемент",
|
||||||
|
|
@ -1853,6 +1858,11 @@ export default {
|
||||||
description: "Автоматизируйте уведомления во внешние сервисы при событиях проекта.",
|
description: "Автоматизируйте уведомления во внешние сервисы при событиях проекта.",
|
||||||
title: "Вебхуки",
|
title: "Вебхуки",
|
||||||
add_webhook: "Добавить вебхук",
|
add_webhook: "Добавить вебхук",
|
||||||
|
delete: {
|
||||||
|
title: "Удалить вебхук",
|
||||||
|
description:
|
||||||
|
"Вы уверены, что хотите удалить этот вебхук? События больше не будут отправляться в этот вебхук. Это действие нельзя отменить.",
|
||||||
|
},
|
||||||
modal: {
|
modal: {
|
||||||
title: "Создать вебхук",
|
title: "Создать вебхук",
|
||||||
details: "Детали вебхука",
|
details: "Детали вебхука",
|
||||||
|
|
@ -2045,6 +2055,12 @@ export default {
|
||||||
heading: "Статусы",
|
heading: "Статусы",
|
||||||
description: "Определяйте и настраивайте статусы рабочего процесса для отслеживания прогресса рабочих элементов.",
|
description: "Определяйте и настраивайте статусы рабочего процесса для отслеживания прогресса рабочих элементов.",
|
||||||
describe_this_state_for_your_members: "Опишите этот статус для участников",
|
describe_this_state_for_your_members: "Опишите этот статус для участников",
|
||||||
|
delete: {
|
||||||
|
blocked: "В этом статусе есть рабочие элементы. Переместите их в другой статус, чтобы удалить текущий.",
|
||||||
|
error: "Не удалось удалить статус. Попробуйте снова.",
|
||||||
|
disabled_default: "Нельзя удалить статус по умолчанию.",
|
||||||
|
disabled_last: "Нельзя оставить группу без статусов.",
|
||||||
|
},
|
||||||
empty_state: {
|
empty_state: {
|
||||||
title: "Нет статусов для группы {groupKey}",
|
title: "Нет статусов для группы {groupKey}",
|
||||||
description: "Создайте новый статус",
|
description: "Создайте новый статус",
|
||||||
|
|
@ -2073,6 +2089,17 @@ export default {
|
||||||
label: "Оценки",
|
label: "Оценки",
|
||||||
title: "Включить оценки для моего проекта",
|
title: "Включить оценки для моего проекта",
|
||||||
enable_description: "Они помогают вам в общении о сложности и рабочей нагрузке команды.",
|
enable_description: "Они помогают вам в общении о сложности и рабочей нагрузке команды.",
|
||||||
|
delete_modal: {
|
||||||
|
title: "Удалить систему оценок",
|
||||||
|
description:
|
||||||
|
'Удаление системы оценок "{value}" безвозвратно уберет её из всех рабочих элементов проекта. Если вы включите оценки снова, рабочие элементы придется настраивать заново.',
|
||||||
|
submit: "Удалить систему оценок",
|
||||||
|
loading: "Удаление",
|
||||||
|
success_title: "Система оценок удалена",
|
||||||
|
success_message: "Система оценок удалена из проекта.",
|
||||||
|
error_title: "Не удалось удалить систему оценок",
|
||||||
|
error_message: "Мы не смогли удалить систему оценок. Попробуйте снова.",
|
||||||
|
},
|
||||||
list_heading: "Список оценок",
|
list_heading: "Список оценок",
|
||||||
archived_heading: "Архивные оценки",
|
archived_heading: "Архивные оценки",
|
||||||
archived_description: "Это оценки из предыдущих версий проекта, которые сейчас не используются. Подробнее о них",
|
archived_description: "Это оценки из предыдущих версий проекта, которые сейчас не используются. Подробнее о них",
|
||||||
|
|
@ -2461,6 +2488,14 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
project_page: {
|
project_page: {
|
||||||
|
delete_modal: {
|
||||||
|
title: "Удалить страницу",
|
||||||
|
content: 'Вы уверены, что хотите удалить страницу "{value}"? Страница будет удалена без возможности восстановления.',
|
||||||
|
success_title: "Страница удалена",
|
||||||
|
success_message: "Страница успешно удалена.",
|
||||||
|
error_title: "Не удалось удалить страницу",
|
||||||
|
error_message: "Не удалось удалить страницу. Попробуйте снова.",
|
||||||
|
},
|
||||||
empty_state: {
|
empty_state: {
|
||||||
general: {
|
general: {
|
||||||
title: "Создавайте заметки, документы или базу знаний. Используйте Galileo, ИИ-помощник NODE.DC.",
|
title: "Создавайте заметки, документы или базу знаний. Используйте Galileo, ИИ-помощник NODE.DC.",
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,8 @@ export interface DialogTitleProps extends React.ComponentProps<typeof BaseDialog
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const OVERLAY_CLASSNAME = cn("fixed inset-0 z-90 bg-backdrop/70 backdrop-blur-sm");
|
const OVERLAY_CLASSNAME = cn("fixed inset-0 z-90 bg-black/60 backdrop-blur-md");
|
||||||
const BASE_CLASSNAME =
|
const BASE_CLASSNAME = "nodedc-glass-modal relative z-100 w-full rounded-[28px] text-left";
|
||||||
"nodedc-glass-modal relative w-full rounded-[28px] border border-subtle/70 bg-surface-1/78 text-left shadow-[0_16px_48px_rgba(0,0,0,0.34)] backdrop-blur-2xl z-100";
|
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
const getPositionClassNames = (position: DialogPosition) =>
|
const getPositionClassNames = (position: DialogPosition) =>
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ export function ModalPortal({
|
||||||
const positionClass = fullScreen ? "" : PORTAL_POSITION_CLASSES[position];
|
const positionClass = fullScreen ? "" : PORTAL_POSITION_CLASSES[position];
|
||||||
|
|
||||||
return cn(
|
return cn(
|
||||||
"nodedc-glass-modal absolute top-0 h-full rounded-[28px] border border-subtle/70 bg-surface-1/78 shadow-[0_16px_48px_rgba(0,0,0,0.34)] backdrop-blur-2xl transition-transform duration-300 ease-out",
|
"nodedc-glass-modal absolute top-0 h-full rounded-[28px] transition-transform duration-300 ease-out",
|
||||||
widthClass,
|
widthClass,
|
||||||
positionClass,
|
positionClass,
|
||||||
contentClassName
|
contentClassName
|
||||||
|
|
@ -101,7 +101,7 @@ export function ModalPortal({
|
||||||
>
|
>
|
||||||
{showOverlay && (
|
{showOverlay && (
|
||||||
<div
|
<div
|
||||||
className={cn("absolute inset-0 bg-black/50 backdrop-blur-sm transition-colors duration-300", overlayClassName)}
|
className={cn("absolute inset-0 bg-black/60 backdrop-blur-md transition-colors duration-300", overlayClassName)}
|
||||||
onClick={handleOverlayClick}
|
onClick={handleOverlayClick}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
"@headlessui/react": "^1.7.3",
|
"@headlessui/react": "^1.7.3",
|
||||||
"@plane/constants": "workspace:*",
|
"@plane/constants": "workspace:*",
|
||||||
"@plane/hooks": "workspace:*",
|
"@plane/hooks": "workspace:*",
|
||||||
|
"@plane/i18n": "workspace:*",
|
||||||
"@plane/propel": "workspace:*",
|
"@plane/propel": "workspace:*",
|
||||||
"@plane/types": "workspace:*",
|
"@plane/types": "workspace:*",
|
||||||
"@plane/utils": "workspace:*",
|
"@plane/utils": "workspace:*",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import type { LucideIcon } from "lucide-react";
|
||||||
import { AlertTriangle, Info } from "lucide-react";
|
import { AlertTriangle, Info } from "lucide-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
// components
|
// components
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
import type { TButtonVariant } from "@plane/propel/button";
|
import type { TButtonVariant } from "@plane/propel/button";
|
||||||
import { Button } from "@plane/propel/button";
|
import { Button } from "@plane/propel/button";
|
||||||
import { cn } from "../utils";
|
import { cn } from "../utils";
|
||||||
|
|
@ -43,16 +44,17 @@ const VARIANT_ICONS: Record<TModalVariant, LucideIcon> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const BUTTON_VARIANTS: Record<TModalVariant, TButtonVariant> = {
|
const BUTTON_VARIANTS: Record<TModalVariant, TButtonVariant> = {
|
||||||
danger: "error-fill",
|
danger: "primary",
|
||||||
primary: "primary",
|
primary: "primary",
|
||||||
};
|
};
|
||||||
|
|
||||||
const VARIANT_CLASSES: Record<TModalVariant, string> = {
|
const VARIANT_CLASSES: Record<TModalVariant, string> = {
|
||||||
danger: "bg-danger-subtle text-danger-primary",
|
danger: "nodedc-modal-alert-icon nodedc-modal-alert-icon-danger",
|
||||||
primary: "bg-accent-primary/20 text-accent-primary",
|
primary: "nodedc-modal-alert-icon nodedc-modal-alert-icon-primary",
|
||||||
};
|
};
|
||||||
|
|
||||||
export function AlertModalCore(props: Props) {
|
export function AlertModalCore(props: Props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const {
|
const {
|
||||||
content,
|
content,
|
||||||
handleClose,
|
handleClose,
|
||||||
|
|
@ -62,10 +64,10 @@ export function AlertModalCore(props: Props) {
|
||||||
isOpen,
|
isOpen,
|
||||||
position = EModalPosition.CENTER,
|
position = EModalPosition.CENTER,
|
||||||
primaryButtonText = {
|
primaryButtonText = {
|
||||||
loading: "Deleting",
|
loading: t("deleting"),
|
||||||
default: "Delete",
|
default: t("delete"),
|
||||||
},
|
},
|
||||||
secondaryButtonText = "Cancel",
|
secondaryButtonText = t("cancel"),
|
||||||
title,
|
title,
|
||||||
variant = "danger",
|
variant = "danger",
|
||||||
width = EModalWidth.XL,
|
width = EModalWidth.XL,
|
||||||
|
|
@ -94,11 +96,11 @@ export function AlertModalCore(props: Props) {
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<div className="text-center sm:text-left">
|
<div className="text-center sm:text-left">
|
||||||
<h3 className="text-18 font-medium text-secondary">{title}</h3>
|
<h3 className="text-18 font-medium text-primary">{title}</h3>
|
||||||
<p className="mt-1 text-13 text-secondary">{content}</p>
|
<p className="mt-1 text-13 text-secondary">{content}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col-reverse gap-3 border-t border-subtle/70 px-6 py-4 sm:flex-row sm:justify-end">
|
<div className="flex flex-col-reverse gap-3 px-6 py-4 sm:flex-row sm:justify-end">
|
||||||
<Button variant="secondary" onClick={handleClose} className="nodedc-modal-secondary-button min-w-[8.25rem]">
|
<Button variant="secondary" onClick={handleClose} className="nodedc-modal-secondary-button min-w-[8.25rem]">
|
||||||
{secondaryButtonText}
|
{secondaryButtonText}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -108,8 +110,8 @@ export function AlertModalCore(props: Props) {
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
loading={isSubmitting}
|
loading={isSubmitting}
|
||||||
className={cn("min-w-[8.25rem]", {
|
className={cn("min-w-[8.25rem]", {
|
||||||
"nodedc-modal-danger-button": variant === "danger",
|
|
||||||
"nodedc-modal-primary-button": variant === "primary",
|
"nodedc-modal-primary-button": variant === "primary",
|
||||||
|
"nodedc-modal-danger-button": variant === "danger",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{isSubmitting ? primaryButtonText.loading : primaryButtonText.default}
|
{isSubmitting ? primaryButtonText.loading : primaryButtonText.default}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export function ModalCore(props: Props) {
|
||||||
leaveFrom="opacity-100"
|
leaveFrom="opacity-100"
|
||||||
leaveTo="opacity-0"
|
leaveTo="opacity-0"
|
||||||
>
|
>
|
||||||
<div className="fixed inset-0 bg-backdrop/70 backdrop-blur-sm transition-opacity" />
|
<div className="fixed inset-0 bg-black/60 backdrop-blur-md transition-opacity" />
|
||||||
</Transition.Child>
|
</Transition.Child>
|
||||||
|
|
||||||
<div className="fixed inset-0 z-30 overflow-y-auto">
|
<div className="fixed inset-0 z-30 overflow-y-auto">
|
||||||
|
|
@ -57,7 +57,7 @@ export function ModalCore(props: Props) {
|
||||||
>
|
>
|
||||||
<Dialog.Panel
|
<Dialog.Panel
|
||||||
className={cn(
|
className={cn(
|
||||||
"nodedc-glass-modal relative w-full transform rounded-[28px] border border-subtle/70 bg-surface-1/78 text-left shadow-[0_16px_48px_rgba(0,0,0,0.34)] backdrop-blur-2xl transition-all",
|
"nodedc-glass-modal relative w-full transform rounded-[28px] text-left transition-all",
|
||||||
width,
|
width,
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1317,6 +1317,9 @@ importers:
|
||||||
'@plane/hooks':
|
'@plane/hooks':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../hooks
|
version: link:../hooks
|
||||||
|
'@plane/i18n':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../i18n
|
||||||
'@plane/propel':
|
'@plane/propel':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../propel
|
version: link:../propel
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue