diff --git a/assets/components/Utils/SnackbarMessage.tsx b/assets/components/Utils/SnackbarMessage.tsx index 0e736a48..f7313a32 100644 --- a/assets/components/Utils/SnackbarMessage.tsx +++ b/assets/components/Utils/SnackbarMessage.tsx @@ -1,9 +1,8 @@ -import { fr } from "@codegouvfr/react-dsfr"; -import Button from "@codegouvfr/react-dsfr/Button"; -import { Slide, SlideProps, Snackbar } from "@mui/material"; -import { FC, memo } from "react"; +import { Slide, SlideProps, Snackbar, SnackbarCloseReason } from "@mui/material"; +import { FC, memo, useEffect, useState } from "react"; import { useSnackbarStore } from "../../stores/SnackbarStore"; +import Alert from "@codegouvfr/react-dsfr/Alert"; function SlideTransition(props: SlideProps) { return ; @@ -11,40 +10,40 @@ function SlideTransition(props: SlideProps) { const SnackbarMessage: FC = () => { const message = useSnackbarStore((state) => state.message); - const messageUuid = useSnackbarStore((state) => state.messageUuid); - const clearMessage = useSnackbarStore((state) => state.clearMessage); + const [open, setOpen] = useState(false); - const handleClose = (_: React.SyntheticEvent | Event, reason?: string) => { - if (reason === "clickaway") { - return; + useEffect(() => { + if (message?.id) { + setOpen(true); + } else { + setOpen(false); } + }, [message?.id]); - clearMessage(); - }; + function handleClose(_, reason: SnackbarCloseReason) { + if (reason !== "clickaway") { + close(); + } + } + + function close() { + setOpen(false); + } return ( - message && ( - -
- - {message} - -   -
-
- ) + + {message ? ( + + ) : undefined} + ); }; diff --git a/assets/components/Utils/TextCopyToClipboard.tsx b/assets/components/Utils/TextCopyToClipboard.tsx index 3159e4b2..1fcba2e8 100644 --- a/assets/components/Utils/TextCopyToClipboard.tsx +++ b/assets/components/Utils/TextCopyToClipboard.tsx @@ -1,44 +1,42 @@ -import { fr, type FrCxArg } from "@codegouvfr/react-dsfr"; +import { fr } from "@codegouvfr/react-dsfr"; import Button from "@codegouvfr/react-dsfr/Button"; -import { FC, memo } from "react"; +import { FC, memo, ReactNode } from "react"; import { symToStr } from "tsafe/symToStr"; import { tss } from "tss-react"; -import { useTranslation } from "../../i18n/i18n"; -import { useSnackbarStore } from "../../stores/SnackbarStore"; +import { useCopyToClipboard } from "@/hooks/useCopyToClipboard"; +import { useTranslation } from "@/i18n"; type TextCopyToClipboardProps = { + label?: string; text: string; - className?: FrCxArg; + title?: string; + className?: string; successMessage?: string; disabled?: boolean; + children?: ReactNode; }; -const TextCopyToClipboard: FC = ({ text, successMessage, className, disabled = false }) => { +const TextCopyToClipboard: FC = (props) => { const { t: tCommon } = useTranslation("Common"); + const { children, label, text, title = tCommon("copy_to_clipboard"), successMessage, className, disabled = false } = props; + const copy = useCopyToClipboard(); + const { classes, cx } = useStyles({ disabled }); - const setMessage = useSnackbarStore((state) => state.setMessage); - - const copyToClipboard = async () => { - await navigator.clipboard.writeText(text); - - setMessage(successMessage ?? tCommon("url_copied")); - }; - - const { classes, cx } = useStyles({ - disabled, - }); + function copyToClipboard() { + copy(text, successMessage); + } return (
+ {label && ( + + {label} : + + )} {text} -
); }; @@ -58,10 +56,11 @@ const useStyles = tss position: "relative", gap: fr.spacing("2v"), flexWrap: "nowrap", + alignItems: "center", }, textBox: { display: "block", - width: "100%", + flex: "1", borderRadius: "0.25rem 0.25rem 0 0", color: disabled ? fr.colors.decisions.text.disabled.grey.default : fr.colors.decisions.text.default.grey.default, userSelect: disabled ? "none" : "auto", @@ -69,6 +68,6 @@ const useStyles = tss overflow: disabled ? "hidden" : "auto", backgroundColor: disabled ? fr.colors.decisions.background.disabled.grey.default : fr.colors.decisions.background.alt.blueFrance.default, padding: fr.spacing("2v"), - whiteSpace: "nowrap", + whiteSpace: "pre", }, })); diff --git a/assets/entrepot/pages/datasheet/DatasheetView/ServiceListTab/ServicesListItem.tsx b/assets/entrepot/pages/datasheet/DatasheetView/ServiceListTab/ServicesListItem.tsx index 2b491fd8..8cc15965 100644 --- a/assets/entrepot/pages/datasheet/DatasheetView/ServiceListTab/ServicesListItem.tsx +++ b/assets/entrepot/pages/datasheet/DatasheetView/ServiceListTab/ServicesListItem.tsx @@ -12,11 +12,12 @@ import OfferingStatusBadge from "../../../../../components/Utils/Badges/Offering import Wait from "../../../../../components/Utils/Wait"; import RQKeys from "../../../../../modules/entrepot/RQKeys"; import { routes } from "../../../../../router/router"; -import { useSnackbarStore } from "../../../../../stores/SnackbarStore"; import { offeringTypeDisplayName } from "../../../../../utils"; import api from "../../../../api"; import ServiceDesc from "./ServiceDesc"; import ListItem from "../ListItem"; +import { useCopyToClipboard } from "@/hooks/useCopyToClipboard"; +import { useSnackbarStore } from "@/stores/SnackbarStore"; type ServicesListItemProps = { service: Service; @@ -25,8 +26,8 @@ type ServicesListItemProps = { }; const ServicesListItem: FC = ({ service, datasheetName, datastoreId }) => { const queryClient = useQueryClient(); - const setMessage = useSnackbarStore((state) => state.setMessage); + const copy = useCopyToClipboard(); const unpublishServiceConfirmModal = createModal({ id: `unpublish-service-confirm-modal-${service._id}`, @@ -73,9 +74,7 @@ const ServicesListItem: FC = ({ service, datasheetName, d if (!service.share_url) { setMessage("URL de diffusion indisponible"); } else { - await navigator.clipboard.writeText(service.share_url); - - setMessage("URL copiée"); + copy(service.share_url); } }, }, diff --git a/assets/entrepot/pages/users/keys/UserKeysListTab/UserKeyLink.tsx b/assets/entrepot/pages/users/keys/UserKeysListTab/UserKeyLink.tsx index becbb79d..5d86a85f 100644 --- a/assets/entrepot/pages/users/keys/UserKeysListTab/UserKeyLink.tsx +++ b/assets/entrepot/pages/users/keys/UserKeysListTab/UserKeyLink.tsx @@ -6,7 +6,7 @@ import { PermissionWithOfferingsDetailsResponseDto } from "../../../../../@types import { fr } from "@codegouvfr/react-dsfr"; import Button from "@codegouvfr/react-dsfr/Button"; import { useTranslation } from "../../../../../i18n/i18n"; -import { useSnackbarStore } from "../../../../../stores/SnackbarStore"; +import TextCopyToClipboard from "@/components/Utils/TextCopyToClipboard"; type UserKeyLinkProps = { permissionId: string; @@ -17,8 +17,6 @@ type UserKeyLinkProps = { const UserKeyLink: FC = ({ permissionId, hash, offeringId }) => { const { t: tCommon } = useTranslation("Common"); - const setMessage = useSnackbarStore((state) => state.setMessage); - const { data: permission } = useQuery({ queryKey: RQKeys.get_permission(permissionId), queryFn: ({ signal }) => api.user.getPermission(permissionId, { signal }), @@ -38,54 +36,26 @@ const UserKeyLink: FC = ({ permissionId, hash, offeringId }) = return (
{wmtsCapabilitiesUrl && ( - <> - WMTS -
- -
- + +
- + +