In-App Docs: tooltips

This commit is contained in:
Aine 2025-05-20 12:16:40 +03:00
parent 5bec4c71ea
commit 319c7aa33a
No known key found for this signature in database
GPG Key ID: 34969C908CCA2804
5 changed files with 144 additions and 97 deletions

View File

@ -1,7 +1,7 @@
import ActionCheck from "@mui/icons-material/CheckCircle"; import ActionCheck from "@mui/icons-material/CheckCircle";
import ActionDelete from "@mui/icons-material/Delete"; import ActionDelete from "@mui/icons-material/Delete";
import AlertError from "@mui/icons-material/ErrorOutline"; import AlertError from "@mui/icons-material/ErrorOutline";
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material"; import { Button, Tooltip, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material";
import { Fragment, useState } from "react"; import { Fragment, useState } from "react";
import { import {
SimpleForm, SimpleForm,
@ -63,6 +63,7 @@ const DeleteRoomButton: React.FC<DeleteRoomButtonProps> = props => {
return ( return (
<Fragment> <Fragment>
<Tooltip title={translate("ra.action.delete")}>
<Button <Button
onClick={handleDialogOpen} onClick={handleDialogOpen}
disabled={isLoading} disabled={isLoading}
@ -79,6 +80,7 @@ const DeleteRoomButton: React.FC<DeleteRoomButtonProps> = props => {
> >
{translate("ra.action.delete")} {translate("ra.action.delete")}
</Button> </Button>
</Tooltip>
<Dialog open={open} onClose={handleDialogClose}> <Dialog open={open} onClose={handleDialogClose}>
<DialogTitle>{translate(props.confirmTitle)}</DialogTitle> <DialogTitle>{translate(props.confirmTitle)}</DialogTitle>
<DialogContent> <DialogContent>

View File

@ -1,7 +1,7 @@
import ActionCheck from "@mui/icons-material/CheckCircle"; import ActionCheck from "@mui/icons-material/CheckCircle";
import ActionDelete from "@mui/icons-material/Delete"; import ActionDelete from "@mui/icons-material/Delete";
import AlertError from "@mui/icons-material/ErrorOutline"; import AlertError from "@mui/icons-material/ErrorOutline";
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material"; import { Tooltip, Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material";
import { Fragment, useState } from "react"; import { Fragment, useState } from "react";
import { import {
SimpleForm, SimpleForm,
@ -69,6 +69,7 @@ const DeleteUserButton: React.FC<DeleteUserButtonProps> = props => {
return ( return (
<Fragment> <Fragment>
<Tooltip title={translate("ra.action.delete")}>
<Button <Button
onClick={handleDialogOpen} onClick={handleDialogOpen}
disabled={isLoading} disabled={isLoading}
@ -85,6 +86,7 @@ const DeleteUserButton: React.FC<DeleteUserButtonProps> = props => {
> >
{translate("ra.action.delete")} {translate("ra.action.delete")}
</Button> </Button>
</Tooltip>
<Dialog open={open} onClose={handleDialogClose}> <Dialog open={open} onClose={handleDialogClose}>
<DialogTitle>{translate(props.confirmTitle)}</DialogTitle> <DialogTitle>{translate(props.confirmTitle)}</DialogTitle>
<DialogContent> <DialogContent>

View File

@ -1,8 +1,11 @@
import { Tooltip } from "@mui/material";
import { DeleteWithConfirmButton, DeleteWithConfirmButtonProps, useRecordContext } from "react-admin"; import { DeleteWithConfirmButton, DeleteWithConfirmButtonProps, useRecordContext } from "react-admin";
import { useTranslate } from "react-admin";
import { isASManaged } from "../utils/mxid"; import { isASManaged } from "../utils/mxid";
export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => { export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => {
const translate = useTranslate();
const record = useRecordContext(); const record = useRecordContext();
if (!record) return null; if (!record) return null;
@ -12,6 +15,9 @@ export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => {
} }
return ( return (
<Tooltip
title={isASManagedUser ? translate("resources.devices.action.erase.disabled") : translate("ra.action.delete")}
>
<DeleteWithConfirmButton <DeleteWithConfirmButton
{...props} {...props}
label="ra.action.remove" label="ra.action.remove"
@ -25,6 +31,7 @@ export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => {
name: record.display_name ? record.display_name : record.id, name: record.display_name ? record.display_name : record.id,
}} }}
/> />
</Tooltip>
); );
}; };

View File

@ -1,8 +1,6 @@
import { Stack, Switch, Typography } from "@mui/material"; import { Tooltip, Stack, Switch, Typography } from "@mui/material";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useRecordContext } from "react-admin"; import { useRecordContext, useTranslate, useNotify, useDataProvider } from "react-admin";
import { useNotify } from "react-admin";
import { useDataProvider } from "react-admin";
import { ExperimentalFeaturesModel, SynapseDataProvider } from "../synapse/dataProvider"; import { ExperimentalFeaturesModel, SynapseDataProvider } from "../synapse/dataProvider";
@ -15,6 +13,7 @@ const ExperimentalFeatureRow = (props: {
featureValue: boolean; featureValue: boolean;
updateFeature: (feature_name: string, feature_value: boolean) => void; updateFeature: (feature_name: string, feature_value: boolean) => void;
}) => { }) => {
const translate = useTranslate();
const featureKey = props.featureKey; const featureKey = props.featureKey;
const featureValue = props.featureValue; const featureValue = props.featureValue;
const featureDescription = experimentalFeaturesMap[featureKey] ?? ""; const featureDescription = experimentalFeaturesMap[featureKey] ?? "";
@ -34,7 +33,9 @@ const ExperimentalFeatureRow = (props: {
padding: 2, padding: 2,
}} }}
> >
<Tooltip title={translate("resources.experimental_features.action.toggle")}>
<Switch checked={checked} onChange={handleChange} /> <Switch checked={checked} onChange={handleChange} />
</Tooltip>
<Stack> <Stack>
<Typography <Typography
variant="subtitle1" variant="subtitle1"

View File

@ -50,10 +50,14 @@ const DeleteMediaDialog = ({ open, onClose, onSubmit }) => {
const DeleteMediaToolbar = (props: ToolbarProps) => ( const DeleteMediaToolbar = (props: ToolbarProps) => (
<Toolbar {...props}> <Toolbar {...props}>
<Tooltip title={translate("delete_media.helper.send")}>
<SaveButton label="delete_media.action.send" icon={<DeleteSweepIcon />} /> <SaveButton label="delete_media.action.send" icon={<DeleteSweepIcon />} />
</Tooltip>
<Tooltip title={translate("ra.action.cancel")}>
<Button label="ra.action.cancel" onClick={onClose}> <Button label="ra.action.cancel" onClick={onClose}>
<IconCancel /> <IconCancel />
</Button> </Button>
</Tooltip>
</Toolbar> </Toolbar>
); );
@ -63,9 +67,20 @@ const DeleteMediaDialog = ({ open, onClose, onSubmit }) => {
<DialogContent> <DialogContent>
<DialogContentText>{translate("delete_media.helper.send")}</DialogContentText> <DialogContentText>{translate("delete_media.helper.send")}</DialogContentText>
<SimpleForm toolbar={<DeleteMediaToolbar />} onSubmit={onSubmit}> <SimpleForm toolbar={<DeleteMediaToolbar />} onSubmit={onSubmit}>
<DateTimeInput source="before_ts" label="delete_media.fields.before_ts" defaultValue={0} parse={dateParser} /> <Tooltip title={translate("delete_media.helper.before_ts")}>
<DateTimeInput
source="before_ts"
label="delete_media.fields.before_ts"
defaultValue={0}
parse={dateParser}
/>
</Tooltip>
<Tooltip title={translate("delete_media.helper.size_gt")}>
<NumberInput source="size_gt" label="delete_media.fields.size_gt" defaultValue={0} min={0} step={1024} /> <NumberInput source="size_gt" label="delete_media.fields.size_gt" defaultValue={0} min={0} step={1024} />
</Tooltip>
<Tooltip title={translate("delete_media.helper.keep_profiles")}>
<BooleanInput source="keep_profiles" label="delete_media.fields.keep_profiles" defaultValue={true} /> <BooleanInput source="keep_profiles" label="delete_media.fields.keep_profiles" defaultValue={true} />
</Tooltip>
</SimpleForm> </SimpleForm>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
@ -76,6 +91,7 @@ export const DeleteMediaButton = (props: ButtonProps) => {
const theme = useTheme(); const theme = useTheme();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const notify = useNotify(); const notify = useNotify();
const translate = useTranslate();
const dataProvider = useDataProvider<SynapseDataProvider>(); const dataProvider = useDataProvider<SynapseDataProvider>();
const { mutate: deleteMedia, isPending } = useMutation({ const { mutate: deleteMedia, isPending } = useMutation({
mutationFn: (values: DeleteMediaParams) => dataProvider.deleteMedia(values), mutationFn: (values: DeleteMediaParams) => dataProvider.deleteMedia(values),
@ -95,6 +111,7 @@ export const DeleteMediaButton = (props: ButtonProps) => {
return ( return (
<> <>
<Tooltip title={translate("delete_media.helper.send")}>
<Button <Button
{...props} {...props}
label="delete_media.action.send" label="delete_media.action.send"
@ -113,6 +130,7 @@ export const DeleteMediaButton = (props: ButtonProps) => {
> >
<DeleteSweepIcon /> <DeleteSweepIcon />
</Button> </Button>
</Tooltip>
<DeleteMediaDialog open={open} onClose={closeDialog} onSubmit={deleteMedia} /> <DeleteMediaDialog open={open} onClose={closeDialog} onSubmit={deleteMedia} />
</> </>
); );
@ -123,10 +141,14 @@ const PurgeRemoteMediaDialog = ({ open, onClose, onSubmit }) => {
const PurgeRemoteMediaToolbar = (props: ToolbarProps) => ( const PurgeRemoteMediaToolbar = (props: ToolbarProps) => (
<Toolbar {...props}> <Toolbar {...props}>
<Tooltip title={translate("purge_remote_media.helper.send")}>
<SaveButton label="purge_remote_media.action.send" icon={<DeleteSweepIcon />} /> <SaveButton label="purge_remote_media.action.send" icon={<DeleteSweepIcon />} />
</Tooltip>
<Tooltip title={translate("ra.action.cancel")}>
<Button label="ra.action.cancel" onClick={onClose}> <Button label="ra.action.cancel" onClick={onClose}>
<IconCancel /> <IconCancel />
</Button> </Button>
</Tooltip>
</Toolbar> </Toolbar>
); );
@ -152,6 +174,7 @@ export const PurgeRemoteMediaButton = (props: ButtonProps) => {
const theme = useTheme(); const theme = useTheme();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const notify = useNotify(); const notify = useNotify();
const translate = useTranslate();
const dataProvider = useDataProvider<SynapseDataProvider>(); const dataProvider = useDataProvider<SynapseDataProvider>();
const { mutate: purgeRemoteMedia, isPending } = useMutation({ const { mutate: purgeRemoteMedia, isPending } = useMutation({
mutationFn: (values: DeleteMediaParams) => dataProvider.purgeRemoteMedia(values), mutationFn: (values: DeleteMediaParams) => dataProvider.purgeRemoteMedia(values),
@ -171,6 +194,7 @@ export const PurgeRemoteMediaButton = (props: ButtonProps) => {
return ( return (
<> <>
<Tooltip title={translate("purge_remote_media.helper.send")}>
<Button <Button
{...props} {...props}
label="purge_remote_media.action.send" label="purge_remote_media.action.send"
@ -187,6 +211,7 @@ export const PurgeRemoteMediaButton = (props: ButtonProps) => {
> >
<DeleteSweepIcon /> <DeleteSweepIcon />
</Button> </Button>
</Tooltip>
<PurgeRemoteMediaDialog open={open} onClose={closeDialog} onSubmit={purgeRemoteMedia} /> <PurgeRemoteMediaDialog open={open} onClose={closeDialog} onSubmit={purgeRemoteMedia} />
</> </>
); );
@ -462,6 +487,7 @@ export const ViewMediaButton = ({ mxcURL, label, uploadName, mimetype }) => {
}; };
export const MediaIDField = ({ source }) => { export const MediaIDField = ({ source }) => {
const translate = useTranslate();
const record = useRecordContext(); const record = useRecordContext();
if (!record) { if (!record) {
return null; return null;
@ -484,10 +510,15 @@ export const MediaIDField = ({ source }) => {
mxcURL = `mxc://${homeserver}/${mediaID}`; mxcURL = `mxc://${homeserver}/${mediaID}`;
} }
return <ViewMediaButton mxcURL={mxcURL} label={mediaID} uploadName={uploadName} mimetype={record.media_type} />; return (
<Tooltip title={translate("resources.users_media.action.open")}>
<ViewMediaButton mxcURL={mxcURL} label={mediaID} uploadName={uploadName} mimetype={record.media_type} />
</Tooltip>
);
}; };
export const ReportMediaContent = ({ source }) => { export const ReportMediaContent = ({ source }) => {
const translate = useTranslate();
const record = useRecordContext(); const record = useRecordContext();
if (!record) { if (!record) {
return null; return null;
@ -503,5 +534,9 @@ export const ReportMediaContent = ({ source }) => {
uploadName = decodeURLComponent(get(record, "event_json.content.body")?.toString()); uploadName = decodeURLComponent(get(record, "event_json.content.body")?.toString());
} }
return <ViewMediaButton mxcURL={mxcURL} label={mxcURL} uploadName={uploadName} mimetype={record.media_type} />; return (
<Tooltip title={translate("resources.users_media.action.open")}>
<ViewMediaButton mxcURL={mxcURL} label={mxcURL} uploadName={uploadName} mimetype={record.media_type} />
</Tooltip>
);
}; };