Expose user avatar URL field in the UI (#27)
* wip * some fixes * update readme * update readme * Add option to change/erase any user's avatar * Fix README * Remove mutationMode from Edit * remove log * update readme
This commit is contained in:
@@ -1,16 +1,26 @@
|
||||
import { stringify } from "query-string";
|
||||
|
||||
import { DataProvider, DeleteParams, HttpError, Identifier, Options, RaRecord, fetchUtils } from "react-admin";
|
||||
import {
|
||||
DataProvider,
|
||||
DeleteParams,
|
||||
HttpError,
|
||||
Identifier,
|
||||
Options,
|
||||
RaRecord,
|
||||
UpdateParams,
|
||||
fetchUtils,
|
||||
withLifecycleCallbacks,
|
||||
} from "react-admin";
|
||||
|
||||
import storage from "../storage";
|
||||
import { returnMXID } from "./synapse.ts"
|
||||
import { returnMXID } from "./synapse";
|
||||
import { MatrixError, displayError } from "../components/error";
|
||||
|
||||
// Adds the access token to all requests
|
||||
const jsonClient = async (url: string, options: Options = {}) => {
|
||||
const token = storage.getItem("access_token");
|
||||
console.log("httpClient " + url);
|
||||
if (token != null) {
|
||||
if (token !== null) {
|
||||
options.user = {
|
||||
authenticated: true,
|
||||
token: `Bearer ${token}`,
|
||||
@@ -23,7 +33,9 @@ const jsonClient = async (url: string, options: Options = {}) => {
|
||||
const error = err as HttpError;
|
||||
const errorStatus = error.status;
|
||||
const errorBody = error.body as MatrixError;
|
||||
const errMsg = !!errorBody?.errcode ? displayError(errorBody.errcode, errorStatus, errorBody.error) : displayError("M_INVALID", errorStatus, error.message);
|
||||
const errMsg = !!errorBody?.errcode
|
||||
? displayError(errorBody.errcode, errorStatus, errorBody.error)
|
||||
: displayError("M_INVALID", errorStatus, error.message);
|
||||
|
||||
return Promise.reject(new HttpError(errMsg, errorStatus, errorBody));
|
||||
}
|
||||
@@ -226,8 +238,19 @@ export interface DeleteMediaResult {
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface UploadMediaParams {
|
||||
file: File;
|
||||
filename: string;
|
||||
content_type: string;
|
||||
}
|
||||
|
||||
export interface UploadMediaResult {
|
||||
content_uri: string;
|
||||
}
|
||||
|
||||
export interface SynapseDataProvider extends DataProvider {
|
||||
deleteMedia: (params: DeleteMediaParams) => Promise<DeleteMediaResult>;
|
||||
uploadMedia: (params: UploadMediaParams) => Promise<UploadMediaResult>;
|
||||
}
|
||||
|
||||
const resourceMap = {
|
||||
@@ -500,7 +523,7 @@ function getSearchOrder(order: "ASC" | "DESC") {
|
||||
}
|
||||
}
|
||||
|
||||
const dataProvider: SynapseDataProvider = {
|
||||
const baseDataProvider: SynapseDataProvider = {
|
||||
getList: async (resource, params) => {
|
||||
console.log("getList " + resource);
|
||||
const { user_id, name, guests, deactivated, locked, search_term, destination, valid } = params.filter;
|
||||
@@ -742,6 +765,46 @@ const dataProvider: SynapseDataProvider = {
|
||||
const { json } = await jsonClient(endpoint_url, { method: "POST" });
|
||||
return json as DeleteMediaResult;
|
||||
},
|
||||
|
||||
uploadMedia: async ({ file, filename, content_type }: UploadMediaParams) => {
|
||||
const base_url = storage.getItem("base_url");
|
||||
const uploadMediaURL = `${base_url}/_matrix/media/v3/upload`;
|
||||
|
||||
const { json } = await jsonClient(`${uploadMediaURL}?filename=${filename}`, {
|
||||
method: "POST",
|
||||
body: file,
|
||||
headers: new Headers({
|
||||
Accept: "application/json",
|
||||
"Content-Type": content_type,
|
||||
}) as Headers,
|
||||
});
|
||||
return json as UploadMediaResult;
|
||||
},
|
||||
};
|
||||
|
||||
const dataProvider = withLifecycleCallbacks(baseDataProvider, [
|
||||
{
|
||||
resource: "users",
|
||||
beforeUpdate: async (params: UpdateParams<any>, dataProvider: DataProvider) => {
|
||||
const avatarFile = params.data.avatar_file?.rawFile;
|
||||
const avatarErase = params.data.avatar_erase;
|
||||
|
||||
if (avatarErase) {
|
||||
params.data.avatar_url = "";
|
||||
return params;
|
||||
}
|
||||
|
||||
if (avatarFile instanceof File) {
|
||||
const reponse = await dataProvider.uploadMedia({
|
||||
file: avatarFile,
|
||||
filename: params.data.avatar_file.title,
|
||||
content_type: params.data.avatar_file.rawFile.type,
|
||||
});
|
||||
params.data.avatar_url = reponse.content_uri;
|
||||
}
|
||||
return params;
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
export default dataProvider;
|
||||
|
||||
Reference in New Issue
Block a user