diff --git a/src/components/media.js b/src/components/media.js index a523fa2..604f19d 100644 --- a/src/components/media.js +++ b/src/components/media.js @@ -13,6 +13,7 @@ import { Toolbar, useCreate, useDelete, + useDeleteMany, useNotify, useRefresh, useTranslate, @@ -325,3 +326,41 @@ export const QuarantineMediaButton = props => { ); }; + +export const DeleteMediaBulkButton = ({ selectedIds }) => { + const classes = useStyles(false); + const notify = useNotify(); + const refresh = useRefresh(); + const [deleteMany, { loading }] = useDeleteMany("delete_media"); + + const handleSend = values => { + deleteMany( + { + type: "deleteMany", + resource: "users_media", + payload: { ids: selectedIds }, + }, + { + onSuccess: () => { + notify("resources.delete_media.action.send_success"); + refresh(); + }, + onFailure: () => + notify("resources.delete_media.action.send_failure", "error"), + } + ); + }; + + return ( + + + + ); +}; diff --git a/src/components/users.js b/src/components/users.js index 83694f9..48ba73c 100644 --- a/src/components/users.js +++ b/src/components/users.js @@ -46,12 +46,19 @@ import { TopToolbar, sanitizeListRestProps, NumberField, + BulkActionsToolbar, + DatagridHeaderCell, + useListContext, + FunctionField, + ImageField, } from "react-admin"; import { Link } from "react-router-dom"; import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices"; import { DeviceRemoveButton } from "./devices"; -import { ProtectMediaButton, QuarantineMediaButton } from "./media"; +import { ProtectMediaButton, QuarantineMediaButton, DeleteMediaBulkButton } from "./media"; import { makeStyles } from "@material-ui/core/styles"; +import { TableHead, TableRow, TableCell, Checkbox } from '@material-ui/core'; +import classnames from 'classnames'; const redirect = () => { return { @@ -313,6 +320,128 @@ const UserTitle = ({ record }) => { ); }; + + +const UserMediaDatagridHeader = (props) => { + const { + children, + classes, + className, + hasExpand = false, + hasBulkActions = false, + isRowSelectable, + } = props; + const translate = useTranslate(); + const { + currentSort, + data, + ids, + onSelect, + selectedIds, + setSort, + } = useListContext(props); + + const updateSortCallback = React.useCallback( + event => { + event.stopPropagation(); + const newField = event.currentTarget.dataset.field; + const newOrder = + currentSort.field === newField + ? currentSort.order === 'ASC' + ? 'DESC' + : 'ASC' + : event.currentTarget.dataset.order; + + setSort(newField, newOrder); + }, + [currentSort.field, currentSort.order, setSort] + ); + + const updateSort = setSort ? updateSortCallback : null; + + const handleSelectAll = React.useCallback( + event => { + onSelect( + event.target.checked + ? ids + .filter(id => + isRowSelectable ? isRowSelectable(data[id]) : true + ) + .concat(selectedIds.filter(id => !ids.includes(id))) + : [] + ); + }, + [data, ids, onSelect, isRowSelectable, selectedIds] + ); + + const selectableIds = isRowSelectable + ? ids.filter(id => isRowSelectable(data[id])) + : ids; + + + return ( + + + + + + + + + + {hasExpand && ( + + )} + {hasBulkActions && selectedIds && ( + + 0 && + selectableIds.length > 0 && + selectableIds.every(id => + selectedIds.includes(id) + ) + } + onChange={handleSelectAll} + /> + + )} + {React.Children.map(children, (field, index) => + React.isValidElement(field) ? ( + + ) : null + )} + + + ); +} + export const UserEdit = props => { const classes = useStyles(); const translate = useTranslate(); @@ -472,7 +601,26 @@ export const UserEdit = props => { perPage={50} sort={{ field: "created_ts", order: "DESC" }} > - + } + > + { + let data = { + title: record.upload_name, + imgURL: `${localStorage.getItem("base_url")}/_matrix/media/v1/thumbnail/${localStorage.getItem("home_server")}/${record.media_id}?width=50&height=50&method=crop`, + downloadURL: `${localStorage.getItem("base_url")}/_matrix/media/r0/download/${localStorage.getItem("home_server")}/${record.media_id}`, + } + if (record.media_type.startsWith("image")) { + return window.open(data.downloadURL)} /> + } else { + return "Preview unavailable"; + } + }} + />