refactoring (#178)

* unify components import

* refactor config and app context

* refactor icons

* refactor date, error, mxid and storage

* refactor synapse utils
This commit is contained in:
Aine
2024-11-25 12:51:05 +02:00
committed by GitHub
parent ea0c7a73fd
commit 392fec3186
35 changed files with 200 additions and 206 deletions

View File

@@ -1,8 +1,8 @@
import { CheckForApplicationUpdate, AppBar, TitlePortal, InspectorButton, Confirm, Layout, Logout, Menu, useLogout, UserMenu } from "react-admin";
import { LoginMethod } from "../pages/LoginPage";
import { useEffect, useState, Suspense } from "react";
import { Icons, DefaultIcon } from "./icons";
import { MenuItem, GetConfig, ClearConfig } from "./config";
import { Icons, DefaultIcon } from "../utils/icons";
import { MenuItem, GetConfig, ClearConfig } from "../utils/config";
import Footer from "./Footer";
const AdminUserMenu = () => {
@@ -96,3 +96,5 @@ export const AdminLayout = ({ children }) => {
<Footer />
</>
};
export default AdminLayout;

View File

@@ -3,8 +3,7 @@ import { Avatar, AvatarProps, Badge, Tooltip } from "@mui/material";
import { FieldProps, useRecordContext, useTranslate } from "react-admin";
import { useState, useEffect, useCallback } from "react";
import { fetchAuthenticatedMedia } from "../utils/fetchMedia";
import { isMXID, isASManaged } from "./mxid";
import storage from "../storage";
import { isMXID, isASManaged } from "../utils/mxid";
const AvatarField = ({ source, ...rest }: AvatarProps & FieldProps) => {
const { alt, classes, sizes, sx, variant } = rest;
@@ -74,7 +73,7 @@ const AvatarField = ({ source, ...rest }: AvatarProps & FieldProps) => {
badge = "🛡️";
tooltip = `${translate("resources.users.badge.system_managed")} (${tooltip})`;
}
if (storage.getItem("user_id") === record?.id) {
if (localStorage.getItem("user_id") === record?.id) {
badge = "🧙‍";
tooltip = `${translate("resources.users.badge.you")} (${tooltip})`;
}

View File

@@ -1,5 +1,5 @@
import { DeleteWithConfirmButton, DeleteWithConfirmButtonProps, useRecordContext } from "react-admin";
import { isASManaged } from "./mxid";
import { isASManaged } from "../utils/mxid";
export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => {
const record = useRecordContext();
@@ -26,3 +26,5 @@ export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => {
/>
);
};
export default DeviceRemoveButton;

View File

@@ -93,3 +93,5 @@ export const ExperimentalFeaturesList = () => {
</Stack>
</>
}
export default ExperimentalFeaturesList;

View File

@@ -15,7 +15,8 @@ import {
import { DataProvider, useTranslate } from "ra-core";
import { useDataProvider, useNotify, RaRecord, Title } from "react-admin";
import { generateRandomMxId, generateRandomPassword, returnMXID } from "../synapse/synapse";
import { generateRandomMXID, returnMXID } from "../utils/mxid";
import { generateRandomPassword } from "../utils/password";
const LOGGING = true;
@@ -274,7 +275,7 @@ const FilePicker = () => {
// No need to do a bunch of cryptographic random number getting if
// we are using neither a generated password nor a generated user id.
if (useridMode === "ignore" || userRecord.id === undefined || userRecord.id === "") {
userRecord.id = generateRandomMxId();
userRecord.id = generateRandomMXID();
}
if (passwordMode === false || entry.password === undefined || entry.password === "") {
userRecord.password = generateRandomPassword();
@@ -325,7 +326,7 @@ const FilePicker = () => {
);
} else {
const newRecordData = Object.assign({}, recordData, {
id: generateRandomMxId(),
id: generateRandomMXID(),
});
retries++;
if (retries > 512) {
@@ -570,4 +571,5 @@ const FilePicker = () => {
return [<Title defaultTitle={translate("import_users.title")} />, cardContainer];
};
export const ImportFeature = FilePicker;
export const UserImport = FilePicker;
export default UserImport;

View File

@@ -46,7 +46,7 @@ const RateLimitRow = ({ limit, value, updateRateLimit }: { limit: string, value:
</Stack>
}
export const UserRateLimits = () => {
const UserRateLimits = () => {
const translate = useTranslate();
const notify = useNotify();
const record = useRecordContext();
@@ -93,3 +93,5 @@ export const UserRateLimits = () => {
</Stack>
</>
};
export default UserRateLimits;

View File

@@ -1,84 +0,0 @@
import storage from "../storage";
export interface Config {
restrictBaseUrl: string | string[];
asManagedUsers: RegExp[];
menu: MenuItem[];
}
export interface MenuItem {
label: string;
icon: string;
url: string;
}
export const WellKnownKey = "cc.etke.synapse-admin";
// current configuration
let config: Config = {
restrictBaseUrl: "",
asManagedUsers: [],
menu: [],
};
export const FetchConfig = async () => {
try {
const resp = await fetch("config.json");
const configJSON = await resp.json();
console.log("Loaded config.json", configJSON);
LoadConfig(configJSON);
} catch (e) {
console.error(e);
}
// if home_server is set, try to load https://home_server/.well-known/matrix/client
const homeserver = storage.getItem("home_server");
if (homeserver) {
try {
const resp = await fetch(`https://${homeserver}/.well-known/matrix/client`);
const configWK = await resp.json();
if (!configWK[WellKnownKey]) {
console.log(`Loaded https://${homeserver}.well-known/matrix/client, but it doesn't contain ${WellKnownKey} key, skipping`, configWK);
} else {
console.log(`Loaded https://${homeserver}.well-known/matrix/client`, configWK);
LoadConfig(configWK[WellKnownKey]);
}
} catch (e) {
console.log(`https://${homeserver}/.well-known/matrix/client not found, skipping`, e);
}
}
}
// load config from context
export const LoadConfig = (context: any) => {
if (context?.restrictBaseUrl) {
config.restrictBaseUrl = context.restrictBaseUrl as string | string[];
}
if (context?.asManagedUsers) {
config.asManagedUsers = context.asManagedUsers.map((regex: string) => new RegExp(regex));
}
let menu: MenuItem[] = [];
if (context?.menu) {
menu = context.menu as MenuItem[];
}
if (menu.length > 0) {
config.menu = menu;
}
}
// get config
export const GetConfig = (): Config => {
return config;
}
// clear config
export const ClearConfig = () => {
// config.json
config = {} as Config;
// session
storage.clear();
}

View File

@@ -1,28 +0,0 @@
export const DATE_FORMAT: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
};
export const dateParser = (v: string | number | Date): number => {
const d = new Date(v);
return d.getTime();
};
export const dateFormatter = (v: string | number | Date | undefined | null): string => {
if (v === undefined || v === null) return "";
const d = new Date(v);
const pad = "00";
const year = d.getFullYear().toString();
const month = (pad + (d.getMonth() + 1).toString()).slice(-2);
const day = (pad + d.getDate().toString()).slice(-2);
const hour = (pad + d.getHours().toString()).slice(-2);
const minute = (pad + d.getMinutes().toString()).slice(-2);
// target format yyyy-MM-ddThh:mm
return `${year}-${month}-${day}T${hour}:${minute}`;
};

View File

@@ -1,6 +0,0 @@
export type MatrixError = {
errcode: string;
error: string;
}
export const displayError = (errcode: string, status: number, message: string) => `${errcode} (${status}): ${message}`;

View File

@@ -1,12 +0,0 @@
import { lazy } from "react";
export const Icons = {
Announcement: lazy(() => import('@mui/icons-material/Announcement')),
Engineering: lazy(() => import('@mui/icons-material/Engineering')),
HelpCenter: lazy(() => import('@mui/icons-material/HelpCenter')),
SupportAgent: lazy(() => import('@mui/icons-material/SupportAgent')),
Default: lazy(() => import('@mui/icons-material/OpenInNew')),
// Add more icons as needed
};
export const DefaultIcon = Icons.Default;

View File

@@ -32,9 +32,8 @@ import {
} from "react-admin";
import { useMutation } from "@tanstack/react-query";
import { dateParser } from "./date";
import { dateParser } from "../utils/date";
import { DeleteMediaParams, SynapseDataProvider } from "../synapse/dataProvider";
import storage from "../storage";
import { fetchAuthenticatedMedia } from "../utils/fetchMedia";
const DeleteMediaDialog = ({ open, onClose, onSubmit }) => {
@@ -385,7 +384,7 @@ export const MediaIDField = ({ source }) => {
if (!record) {
return null;
}
const homeserver = storage.getItem("home_server");
const homeserver = localStorage.getItem("home_server");
const mediaID = get(record, source)?.toString();
if (!mediaID) {

View File

@@ -1,20 +0,0 @@
import { Identifier } from "ra-core";
import { GetConfig } from "./config";
const mxidPattern = /^@[^@:]+:[^@:]+$/;
/*
* Check if id is a valid Matrix ID (user)
* @param id The ID to check
* @returns Whether the ID is a valid Matrix ID
*/
export const isMXID = (id: string | Identifier): boolean => mxidPattern.test(id as string);
/**
* Check if a user is managed by an application service
* @param id The user ID to check
* @returns Whether the user is managed by an application service
*/
export const isASManaged = (id: string | Identifier): boolean => {
return GetConfig().asManagedUsers.some(regex => regex.test(id as string));
};