import React, { Fragment } from "react"; import { connect } from "react-redux"; import { Route, Link } from "react-router-dom"; import { AutocompleteArrayInput, AutocompleteInput, BooleanInput, BooleanField, BulkDeleteButton, Button, Create, Edit, Datagrid, DateField, DeleteButton, Filter, FormTab, List, NumberField, Pagination, ReferenceArrayInput, ReferenceField, ReferenceInput, ReferenceManyField, SearchInput, SelectField, Show, SimpleForm, Tab, TabbedForm, TabbedShowLayout, TextField, TextInput, Toolbar, TopToolbar, useDataProvider, useRecordContext, useRefresh, useTranslate, } from "react-admin"; import get from "lodash/get"; import PropTypes from "prop-types"; import { makeStyles } from "@material-ui/core/styles"; import { Tooltip, Typography, Chip, Drawer, styled, withStyles, Select, MenuItem, } from "@material-ui/core"; import FastForwardIcon from "@material-ui/icons/FastForward"; import HttpsIcon from "@material-ui/icons/Https"; import NoEncryptionIcon from "@material-ui/icons/NoEncryption"; import PageviewIcon from "@material-ui/icons/Pageview"; import UserIcon from "@material-ui/icons/Group"; import ViewListIcon from "@material-ui/icons/ViewList"; import VisibilityIcon from "@material-ui/icons/Visibility"; import ContentSave from "@material-ui/icons/Save"; import EventIcon from "@material-ui/icons/Event"; import { RoomDirectoryBulkDeleteButton, RoomDirectoryBulkSaveButton, RoomDirectoryDeleteButton, RoomDirectorySaveButton, } from "./RoomDirectory"; const useStyles = makeStyles(theme => ({ helper_forward_extremities: { fontFamily: "Roboto, Helvetica, Arial, sans-serif", margin: "0.5em", }, })); const RoomPagination = props => ( ); const EncryptionField = ({ source, record = {}, emptyText }) => { const translate = useTranslate(); const value = get(record, source); let ariaLabel = value === false ? "ra.boolean.false" : "ra.boolean.true"; if (value === false || value === true) { return ( {value === true ? ( ) : ( )} ); } return ( {emptyText} ); }; const validateDisplayName = fieldval => { return fieldval == null ? "synapseadmin.rooms.room_name_required" : fieldval.length === 0 ? "synapseadmin.rooms.room_name_required" : undefined; }; function approximateAliasLength(alias, homeserver) { /* TODO maybe handle punycode in homeserver name */ var te; // Support for TextEncoder is quite widespread, but the polyfill is // pretty large; We will only underestimate the size with the regular // length attribute of String, so we never prevent the user from using // an alias that is short enough for the server, but too long for our // heuristic. try { te = new TextEncoder(); } catch (err) { if (err instanceof ReferenceError) { te = undefined; } } const aliasLength = te === undefined ? alias.length : te.encode(alias).length; return "#".length + aliasLength + ":".length + homeserver.length; } const validateAlias = fieldval => { if (fieldval === undefined) { return undefined; } const homeserver = localStorage.getItem("home_server"); if (approximateAliasLength(fieldval, homeserver) > 255) { return "synapseadmin.rooms.alias_too_long"; } }; const removeLeadingWhitespace = fieldVal => fieldVal === undefined ? undefined : fieldVal.trimStart(); const replaceAllWhitespace = fieldVal => fieldVal === undefined ? undefined : fieldVal.replace(/\s/, "_"); const removeLeadingSigil = fieldVal => fieldVal === undefined ? undefined : fieldVal.startsWith("#") ? fieldVal.substr(1) : fieldVal; const validateHasAliasIfPublic = formdata => { let errors = {}; if (formdata.public) { if ( formdata.canonical_alias === undefined || formdata.canonical_alias.trim().length === 0 ) { errors.canonical_alias = "synapseadmin.rooms.alias_required_if_public"; } } return errors; }; export const RoomCreate = props => ( }> replaceAllWhitespace(removeLeadingSigil(fv))} validate={validateAlias} placeholder="#" /> ({ user_id: searchText })} > } > ({ user_id: searchText })} > ); const RoomTitle = ({ record }) => { const translate = useTranslate(); return ( {translate("resources.rooms.name", 1)} {record ? `"${record.name}"` : ""} ); }; // Explicitely passing "to" prop // Toolbar adds all kinds of unsupported props to its children :( const StyledLink = styles => { const Styled = styled(Link)(styles); return ({ to, children }) => {children}; }; const RoomMemberEditToolbar = ({ backLink, translate, onSave, ...props }) => { const SaveLink = StyledLink({ textDecoration: "none", }); const CancelLink = StyledLink({ textDecoration: "none", marginLeft: "1em", }); const SaveIcon = styled(ContentSave)({ width: "1rem", marginRight: "0.25em", }); return ( ); }; const RoomMemberIdField = ({ memberId, data = {} }) => { const value = get(data[memberId], "id"); return ( {value} ); }; const RoomMemberRoleInput = ({ memberId, data = {}, translate, onChange }) => { const roleValue = get(data[memberId], "role"); const [role, setRole] = React.useState(roleValue); React.useEffect(() => { onChange(roleValue); }, [onChange, roleValue]); return ( ); }; const RoomMemberEdit = ({ backLink, memberId, ...props }) => { const translate = useTranslate(); const refresh = useRefresh(); const dataProvider = useDataProvider(); const [role, setRole] = React.useState(); const { id } = props; return ( { dataProvider .update("rooms", { data: { id, member_roles: [{ member_id: memberId, role }], }, }) .then(() => { refresh(); }); }} /> } > ); }; const drawerStyles = { paper: { width: 300, }, }; const StyledDrawer = withStyles(drawerStyles)(({ classes, ...props }) => ( )); export const RoomEdit = props => { const translate = useTranslate(); return ( }> }> ({ user_id: searchText })} > `/rooms/${encodeURIComponent( record.parentId )}/${encodeURIComponent(id)}` } > {({ match }) => { const isMatch = !!match && !!match.params; return ( {isMatch ? ( ) : (
)} ); }} ); }; const RoomShowActions = ({ basePath, data, resource }) => { var roomDirectoryStatus = ""; if (data) { roomDirectoryStatus = data.public; } return ( {roomDirectoryStatus === false && ( )} {roomDirectoryStatus === true && ( )} ); }; export const RoomShow = props => { const classes = useStyles({ props }); const translate = useTranslate(); return ( } title={}> }> } path="detail" > }> "/users/" + id} > } path="permission" > } path="state" > } path="forward_extremities" >
{translate("resources.rooms.helper.forward_extremities")}
); }; const RoomBulkActionButtons = props => ( ); const RoomFilter = ({ ...props }) => { const translate = useTranslate(); return ( ); }; const RoomNameField = props => { const { source } = props; const record = useRecordContext(props); return ( {record[source] || record["canonical_alias"] || record["id"]} ); }; RoomNameField.propTypes = { label: PropTypes.string, record: PropTypes.object, source: PropTypes.string.isRequired, }; const FilterableRoomList = ({ roomFilters, dispatch, ...props }) => { const filter = roomFilters; const localMembersFilter = filter && filter.joined_local_members ? true : false; const stateEventsFilter = filter && filter.state_events ? true : false; const versionFilter = filter && filter.version ? true : false; const federateableFilter = filter && filter.federatable ? true : false; return ( } sort={{ field: "name", order: "ASC" }} filters={} bulkActionButtons={} > } /> {localMembersFilter && } {stateEventsFilter && } {versionFilter && } {federateableFilter && } ); }; function mapStateToProps(state) { return { roomFilters: state.admin.resources.rooms.list.params.displayedFilters, }; } export const RoomList = connect(mapStateToProps)(FilterableRoomList);