feat: add the old UserRightPanel to the new UsersTab

pull/15/head
c-cal 6 years ago
parent b1fd5e050f
commit 3933e62263
Signed by: watcha
GPG Key ID: 87DD78E7F7A1581D
  1. 2
      public/locales/en/common.json
  2. 2
      public/locales/fr/common.json
  3. 18
      src/Table.js
  4. 6
      src/TableTab.js
  5. 247
      src/UserRightPanel.js
  6. 73
      src/UsersTab.js

@ -35,7 +35,7 @@
"roles": {
"administrator": "Administrator",
"collaborator": "Collaborator",
"partners": "Partners"
"partner": "Partner"
},
"isActive": {
"1": "enabled",

@ -91,7 +91,7 @@
"roles": {
"administrator": "Administrateur",
"collaborator": "Collaborateur",
"partners": "Partenaire"
"partner": "Partenaire"
},
"isActive": {
"1": "activé",

@ -1,8 +1,8 @@
import React from "react";
import React, { useEffect } from "react";
import classNames from "classnames";
import Table from "react-bootstrap/Table";
export default ({ tableInstance }) => {
export default ({ tableInstance, editUser }) => {
const {
getTableProps,
getTableBodyProps,
@ -11,6 +11,13 @@ export default ({ tableInstance }) => {
prepareRow,
} = tableInstance;
useEffect(() => {
const row = tableInstance.selectedFlatRows[0];
if (row) {
editUser(row.original);
}
}, [tableInstance.selectedFlatRows, editUser]);
const getHeaderProps = column =>
column.getHeaderProps(
column.getSortByToggleProps({ title: undefined })
@ -33,11 +40,16 @@ export default ({ tableInstance }) => {
tableInstance.toggleAllRowsSelected(false);
if (isNotSelected) {
row.toggleRowSelected(true);
editUser(row.original);
} else {
editUser();
}
};
const onBlur = () => tableInstance.toggleAllRowsSelected(false);
return (
<Table hover size="sm" {...getTableProps()}>
<Table hover size="sm" {...getTableProps({ onBlur, tabIndex: "0" })}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>

@ -10,7 +10,7 @@ import matchSorter from "match-sorter";
import SearchBox from "./SearchBox";
import Table from "./Table";
export default ({ data, columns, initialState, button, panel }) => {
export default ({ data, columns, initialState, button, rightPanel, editUser }) => {
const globalFilter = useMemo(() => fuzzyTextFilterFn, []);
const tableInstance = useTable(
@ -37,9 +37,9 @@ export default ({ data, columns, initialState, button, panel }) => {
</div>
<div className="tableTabBody">
<div className="tableContainer px-3">
<Table {...{ tableInstance }} />
<Table {...{ tableInstance, editUser }} />
</div>
{panel}
{rightPanel}
</div>
</>
);

@ -4,7 +4,6 @@ import Accordion from "react-bootstrap/Accordion";
import Alert from "react-bootstrap/Alert";
import Button from "react-bootstrap/Button";
import Card from "react-bootstrap/Card";
import Collapse from "react-bootstrap/Collapse";
import Table from "react-bootstrap/Table";
import { MatrixClientContext } from "./contexts";
@ -13,7 +12,6 @@ class UserRightPanel extends Component {
constructor(props) {
super(props);
this.state = {
open: true,
editEmail: false,
isEmail: false,
emailValue: " ",
@ -25,8 +23,8 @@ class UserRightPanel extends Component {
static contextType = MatrixClientContext;
componentDidMount() {
if (this.props.data["Email"]["data"]) {
this.setState({ emailValue: this.props.data["Email"]["data"] });
if (this.props.user.emailAddress) {
this.setState({ emailValue: this.props.user.emailAddress });
} else {
this.setState({ emailValue: " " });
}
@ -34,10 +32,10 @@ class UserRightPanel extends Component {
}
componentDidUpdate(prevProps) {
if (this.props.data !== prevProps.data) {
if (this.props.data["Email"]["data"]) {
if (this.props.user !== prevProps.user) {
if (this.props.user.emailAddress) {
this.setState({
emailValue: this.props.data["Email"]["data"],
emailValue: this.props.user.emailAddress,
editEmail: false,
infoMessage: false,
});
@ -50,7 +48,7 @@ class UserRightPanel extends Component {
onCancelEdit = () =>
this.setState({
emailValue: this.props.data["Email"]["data"],
emailValue: this.props.user.emailAddress,
editEmail: false,
});
@ -72,9 +70,7 @@ class UserRightPanel extends Component {
onEmailValidate = async () => {
const client = this.context;
try {
const userId = encodeURIComponent(
this.props.data["User name"]["data"]
);
const userId = encodeURIComponent(this.props.user.userId);
const SERVER_REQUEST = await fetch(
new URL(
`_matrix/client/r0/watcha_update_email/${userId}`,
@ -97,9 +93,8 @@ class UserRightPanel extends Component {
type: "success",
title: "Email updated",
body:
this.simplifiedUserId(
this.props.data["User name"]["data"]
) + " email has been updated",
this.simplifiedUserId(this.props.user.userId) +
" email has been updated",
},
});
this.displayInfoMessage();
@ -120,15 +115,12 @@ class UserRightPanel extends Component {
}
};
onInfoMessageValidate = () => {
this.props.refreshRightPanel(this.props.data["User name"]["data"]);
this.dismissInfoMessage();
};
onInfoMessageValidate = () => this.dismissInfoMessage();
getDate = date => {
const OPTIONS = { year: "numeric", month: "long", day: "numeric" };
const FORMATED_DATE =
date.toLocaleDateString(this.props.lang, OPTIONS) +
date.toLocaleDateString(this.props.i18n.language, OPTIONS) +
" " +
this.addZero(date.getHours()) +
":" +
@ -139,9 +131,7 @@ class UserRightPanel extends Component {
getUsersAdvancedInfos = async () => {
const client = this.context;
try {
const userId = encodeURIComponent(
this.props.data["User name"]["data"]
);
const userId = encodeURIComponent(this.props.user.userId);
const SERVER_REQUEST = await fetch(
new URL(
`_matrix/client/r0/watcha_user_ip/${userId}`,
@ -187,17 +177,15 @@ class UserRightPanel extends Component {
: t("Password reset");
const messageBody = isActivating
? t("The account ") +
this.simplifiedUserId(this.props.data["User name"]["data"]) +
this.simplifiedUserId(this.props.user.userId) +
t(
" has been reactivated, and an email has been sent to the user with a new password"
)
: t("an email has been send to ") +
this.simplifiedUserId(this.props.data["User name"]["data"]) +
this.simplifiedUserId(this.props.user.userId) +
t(" with a new password");
try {
const userId = encodeURIComponent(
this.props.data["User name"]["data"]
);
const userId = encodeURIComponent(this.props.user.userId);
const SERVER_REQUEST = await fetch(
new URL(
`_matrix/client/r0/watcha_reset_password/${userId}`,
@ -211,7 +199,7 @@ class UserRightPanel extends Component {
"Content-Type": "application/json",
},
body: JSON.stringify({
user: this.props.data["User name"]["data"],
user: this.props.user.userId,
}),
}
);
@ -248,7 +236,7 @@ class UserRightPanel extends Component {
deactivateSynapseUser = () => {
const { t } = this.props;
const client = this.context;
const userId = this.props.data["User name"]["data"];
const userId = this.props.user.userId;
client
.deactivateSynapseUser(userId)
.then(response =>
@ -258,9 +246,8 @@ class UserRightPanel extends Component {
type: "success",
title: t("Account deactivated"),
body:
this.simplifiedUserId(
this.props.data["User name"]["data"]
) + t(" account has been deactivated"),
this.simplifiedUserId(this.props.user.userId) +
t(" account has been deactivated"),
},
},
this.displayInfoMessage
@ -338,9 +325,7 @@ class UserRightPanel extends Component {
upgradePartner = async () => {
const client = this.context;
try {
const userId = encodeURIComponent(
this.props.data["User name"]["data"]
);
const userId = encodeURIComponent(this.props.user.userId);
const SERVER_REQUEST = await fetch(
new URL(
`_matrix/client/r0/watcha_update_partner_to_member/${userId}`,
@ -362,9 +347,8 @@ class UserRightPanel extends Component {
type: "success",
title: "Role updated",
body:
this.simplifiedUserId(
this.props.data["User name"]["data"]
) + " account has been upgraded to internal user",
this.simplifiedUserId(this.props.user.userId) +
" account has been upgraded to internal user",
},
});
this.displayInfoMessage();
@ -385,13 +369,12 @@ class UserRightPanel extends Component {
};
render() {
const ISPARTNER = this.props.data["Status"]["data"] === "Partner";
const ISPARTNER = this.props.user.role === "partner";
const { t } = this.props;
const OPEN = this.props.data ? true : false;
const ISDEACTIVATE = !this.props.data["Active"]["data"];
const ISDEACTIVATE = this.props.user.accountStatus === 0;
let editEmail;
const bottomButtons = [];
let title = t("User");
let title = t(`usersTab.roles.${this.props.user.role}`);
if (ISDEACTIVATE) {
bottomButtons.push(
@ -406,7 +389,6 @@ class UserRightPanel extends Component {
);
} else {
if (ISPARTNER) {
title = t("Partner");
bottomButtons.push(
<Button
className="ActivationButton"
@ -440,10 +422,7 @@ class UserRightPanel extends Component {
</Button>
);
}
let emailPlaceholder = "";
if (this.props.data["email"]) {
emailPlaceholder = this.props.data["email"]["data"];
}
let emailPlaceholder = this.props.user.emailAddress;
editEmail = (
<td>
@ -554,109 +533,85 @@ class UserRightPanel extends Component {
}
return (
<div>
<Collapse in={OPEN} dimension="width" timeout={0}>
<div>
<Card className="rightPanel">
<Card.Header className="header-with-button">
{title +
" : " +
this.simplifiedUserId(
this.props.data["User name"]["data"]
)}
<i
className="fas fa-times dismissRight"
onClick={this.props.onClose}
></i>
</Card.Header>
<div className="mx-3">
<Card className="rightPanel">
<Card.Header className="header-with-button">
{title +
" : " +
this.simplifiedUserId(this.props.user.userId)}
<i
className="fas fa-times dismissRight"
onClick={this.props.onClose}
></i>
</Card.Header>
<div className="pannelContainer">
<Card.Body>
<Card body bg="light">
<Table>
<tbody>
<tr>
<td className="labelText">
{t("Creation")}:
</td>
<td className="infoText">
{
this.props.data[
"Date of creation"
]["data"]
}
</td>
</tr>
{/* we don't display device yet but may be useful for e2e
<tr>
<td className='labelText'>Devices:</td>
<td className='infoText'>{ this.props.data.device }</td>
</tr> */}
<tr>
<td className="labelText">
{t("Email")}:
</td>
{editEmail}
</tr>
</tbody>
</Table>
<Accordion>
<Card id="collapsible-panel-users">
<Card.Header>
<Accordion.Toggle
as={Button}
variant="link"
eventKey="0"
<div className="pannelContainer">
<Card.Body>
<Card body bg="light">
<Table>
<tbody>
<tr>
<td className="labelText">
{t("Creation")}:
</td>
</tr>
<tr>
<td className="labelText">
{t("Email")}:
</td>
{editEmail}
</tr>
</tbody>
</Table>
<Accordion>
<Card id="collapsible-panel-users">
<Card.Header>
<Accordion.Toggle
as={Button}
variant="link"
eventKey="0"
>
{t("Show connection history")}
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>
<div className="TableAdvanced">
<Table
striped
bordered
size="sm"
hover
>
{t(
"Show connection history"
)}
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>
<div className="TableAdvanced">
<Table
striped
bordered
size="sm"
hover
>
<thead>
<tr>
<th>
{t(
"Connected"
)}
</th>
<th>
{t(
"Device"
)}
</th>
<th>
Ip
</th>
</tr>
</thead>
<tbody className="AdvancedUserBody">
{
advancedUserInfos
}
</tbody>
</Table>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
<thead>
<tr>
<th>
{t(
"Connected"
)}
</th>
<th>
{t(
"Device"
)}
</th>
<th>Ip</th>
</tr>
</thead>
<tbody className="AdvancedUserBody">
{advancedUserInfos}
</tbody>
</Table>
</div>
</Card.Body>
</Accordion.Collapse>
</Card>
</Card.Body>
{bottomWell}
</div>
</Card>
</Accordion>
</Card>
</Card.Body>
{bottomWell}
</div>
</Collapse>
</Card>
</div>
);
}

@ -7,12 +7,17 @@ import Date from "./Date";
import DelayedSpinner from "./DelayedSpinner";
import TableTab, { compareLowerCase } from "./TableTab";
import { useDispatchContext, useUserIdContext } from "./contexts";
import CreateUserRightPanel from "./CreateUserRightPanel";
import UserRightPanel from "./UserRightPanel";
export default withTranslation()(({ t }) => {
const userId = useUserIdContext();
const dispatch = useDispatchContext();
const [userList, setUserList] = useState(null);
const [intervalId, setIntervalId] = useState(null);
const [rightPanel, setRightPanel] = useState();
const [rightPanel, setRightPanel] = useState(null);
const { data, refetch } = useGet({
path: "watcha_user_list",
@ -20,19 +25,6 @@ export default withTranslation()(({ t }) => {
resolve,
});
useEffect(() => {
refetch();
}, []);
useEffect(() => {
setUserList(data);
const _intervalId = setInterval(() => refetch(), 10000);
setIntervalId(prevIntervalId => {
prevIntervalId && clearInterval(prevIntervalId);
return _intervalId;
});
}, [data]);
const columns = useMemo(
() => [
{
@ -76,13 +68,6 @@ export default withTranslation()(({ t }) => {
[]
);
const onClick = useCallback(
() => setRightPanel("CreateUserRightPanel"),
[]
);
const button = useMemo(() => <Button {...{ onClick }} />, [onClick]);
const isEmailAvailable = useCallback(
() => value => userList.some(user => user.emailAddress === value),
[userList]
@ -90,14 +75,51 @@ export default withTranslation()(({ t }) => {
const onClose = useCallback(() => setRightPanel(), []);
const panel = rightPanel === "CreateUserRightPanel" && (
<CreateUserRightPanel {...{ isEmailAvailable, onClose }} />
const onClick = useCallback(
() =>
setRightPanel(
<CreateUserRightPanel {...{ isEmailAvailable, onClose }} />
),
[isEmailAvailable, onClose]
);
const button = useMemo(() => <Button {...{ onClick }} />, [onClick]);
const editUser = useCallback(
user =>
setRightPanel(user && <UserRightPanel {...{ user, onClose }} />),
[onClose]
);
useEffect(() => {
refetch();
}, []);
useEffect(() => {
setUserList(data);
const _intervalId = setInterval(() => refetch(), 10000);
setIntervalId(prevIntervalId => {
prevIntervalId && clearInterval(prevIntervalId);
return _intervalId;
});
}, [data]);
useEffect(() => {
if (userList && userId) {
for (const user of userList) {
if (user.userId === userId) {
setRightPanel(<UserRightPanel {...{ user, onClose }} />);
dispatch({ userId: null });
return;
}
}
}
}, [userList, userId, dispatch, onClose]);
return userList ? (
<TableTab
data={userList}
{...{ columns, initialState, button, panel }}
{...{ columns, initialState, button, rightPanel, editUser }}
/>
) : (
<DelayedSpinner />
@ -106,6 +128,7 @@ export default withTranslation()(({ t }) => {
const resolve = data =>
data.map(item => ({
userId: item.name,
displayName: item.displayname || "",
emailAddress: item.email || "",
lastSeen: item.last_seen || null,
@ -113,7 +136,7 @@ const resolve = data =>
item.admin === 1
? "administrator"
: item.is_partner === 1
? "partners"
? "partner"
: "collaborator",
accountStatus: item.is_active,
}));

Loading…
Cancel
Save