Expose user avatar URL field in the UI

To be able to change a avatar the URL field needs to be exposed but
changing the URL alone is difficult. This patch adds a image upload
field to the edit view of a user. If there is a file detected it
uploads it to the servers media repository and sets that new URL
as the avatar URL one. This way a admin can change any users avatar
which is especially nice for bridged users like in the IRC bridge
and bots.
This commit is contained in:
Jeena 2020-08-04 17:38:42 +02:00
parent 1f56bac356
commit 7056dc0fdb
2 changed files with 38 additions and 6 deletions

View File

@ -36,6 +36,8 @@ import {
ExportButton, ExportButton,
TopToolbar, TopToolbar,
sanitizeListRestProps, sanitizeListRestProps,
ImageInput,
ImageField,
} from "react-admin"; } from "react-admin";
import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices"; import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices";
import { DeviceRemoveButton } from "./devices"; import { DeviceRemoveButton } from "./devices";
@ -221,6 +223,9 @@ export const UserEdit = props => {
<TextInput source="id" disabled /> <TextInput source="id" disabled />
<TextInput source="displayname" /> <TextInput source="displayname" />
<PasswordInput source="password" autoComplete="new-password" /> <PasswordInput source="password" autoComplete="new-password" />
<ImageInput source="avatar_file" label="Avatar" accept="image/*">
<ImageField source="avatar_src" title="Avatar" />
</ImageInput>
<BooleanInput source="admin" /> <BooleanInput source="admin" />
<BooleanInput <BooleanInput
source="deactivated" source="deactivated"

View File

@ -32,6 +32,7 @@ const resourceMap = {
...u, ...u,
id: u.name, id: u.name,
avatar_src: mxcUrlToHttp(u.avatar_url), avatar_src: mxcUrlToHttp(u.avatar_url),
avatar_url: u.avatar_url,
is_guest: !!u.is_guest, is_guest: !!u.is_guest,
admin: !!u.admin, admin: !!u.admin,
deactivated: !!u.deactivated, deactivated: !!u.deactivated,
@ -202,12 +203,38 @@ const dataProvider = {
const res = resourceMap[resource]; const res = resourceMap[resource];
const endpoint_url = homeserver + res.path; const endpoint_url = homeserver + res.path;
return jsonClient(`${endpoint_url}/${params.data.id}`, {
method: "PUT", // In case there is a avatar_file object, save it in the media repository
body: JSON.stringify(params.data, filterNullValues), // and update the avatar_url.
}).then(({ json }) => ({ const f = params?.data?.avatar_file?.rawFile;
data: res.map(json), if (f instanceof File) {
})); const file_endpoint =
homeserver + "/_matrix/media/r0/upload?filename=" + f.name;
const headers = new Headers();
headers.append("Content-Type", f.type);
const options = {
method: "POST",
body: f,
headers: headers,
};
return jsonClient(file_endpoint, options).then(r => {
params.data.avatar_url = r.json.content_uri;
return jsonClient(`${endpoint_url}/${params.data.id}`, {
method: "PUT",
body: JSON.stringify(params.data, filterNullValues),
}).then(({ json }) => ({
data: res.map(json),
}));
});
} else {
return jsonClient(`${endpoint_url}/${params.data.id}`, {
method: "PUT",
body: JSON.stringify(params.data, filterNullValues),
}).then(({ json }) => ({
data: res.map(json),
}));
}
}, },
updateMany: (resource, params) => { updateMany: (resource, params) => {