parent
0cf491deee
commit
c57e807904
@ -1,9 +1,17 @@ |
|||||||
import React from "react"; |
import React from "react"; |
||||||
|
import PropTypes from "prop-types"; |
||||||
|
|
||||||
import moment from "moment"; |
import moment from "moment"; |
||||||
|
|
||||||
export default ({ timestamp }) => { |
const Date = ({ timestamp }) => { |
||||||
const m = moment(timestamp); |
const m = moment(timestamp); |
||||||
const shortDate = m.format("L"); |
const shortDate = m.format("L"); |
||||||
const fullDate = m.format("LLLL"); |
const fullDate = m.format("LLLL"); |
||||||
return <span title={fullDate}>{shortDate}</span>; |
return <span title={fullDate}>{shortDate}</span>; |
||||||
}; |
}; |
||||||
|
|
||||||
|
Date.propTypes = { |
||||||
|
timestamp: PropTypes.number.isRequired, |
||||||
|
}; |
||||||
|
|
||||||
|
export default Date; |
@ -1,10 +1,20 @@ |
|||||||
import React from "react"; |
import React from "react"; |
||||||
|
import PropTypes from "prop-types"; |
||||||
|
|
||||||
import Button from "react-bootstrap/Button"; |
import Button from "react-bootstrap/Button"; |
||||||
|
|
||||||
import "./css/NewItemButton.scss"; |
import "./css/NewItemButton.scss"; |
||||||
|
|
||||||
export default ({ onClick, className, t }) => ( |
const NewItemButton = ({ onClick, className, t }) => ( |
||||||
<Button variant="primary" {...{ onClick }} title={t("buttonTooltip")}> |
<Button variant="primary" {...{ onClick }} title={t("buttonTooltip")}> |
||||||
<span className={`NewItemButton ${className}`}>{t("button")}</span> |
<span className={`NewItemButton ${className}`}>{t("button")}</span> |
||||||
</Button> |
</Button> |
||||||
); |
); |
||||||
|
|
||||||
|
NewItemButton.propTypes = { |
||||||
|
onClick: PropTypes.func.isRequired, |
||||||
|
className: PropTypes.string.isRequired, |
||||||
|
t: PropTypes.func.isRequired, |
||||||
|
}; |
||||||
|
|
||||||
|
export default NewItemButton; |
@ -1,66 +0,0 @@ |
|||||||
import React, { useRef, useState } from "react"; |
|
||||||
import { useMutate } from "restful-react"; |
|
||||||
import { useTranslation } from "react-i18next"; |
|
||||||
|
|
||||||
import NewItemModal from "./NewItemModal"; |
|
||||||
import NewUserForm from "./NewUserForm"; |
|
||||||
|
|
||||||
export default ({ modalShow, setModalShow, userList, newUserLocalEcho }) => { |
|
||||||
const { t } = useTranslation("usersTab"); |
|
||||||
|
|
||||||
const [feedback, setFeedback] = useState(null); |
|
||||||
|
|
||||||
const { mutate: post, loading } = useMutate({ |
|
||||||
verb: "POST", |
|
||||||
path: "watcha_register", |
|
||||||
}); |
|
||||||
|
|
||||||
const onSubmit = data => { |
|
||||||
const payload = makePayload(data); |
|
||||||
post(payload) |
|
||||||
.then(response => { |
|
||||||
const user = makeUser(data); |
|
||||||
newUserLocalEcho(user); |
|
||||||
setFeedback({ variant: "success", message: t("success") }); |
|
||||||
}) |
|
||||||
.catch(error => setFeedback({ variant: "danger", message: t("danger") })); |
|
||||||
}; |
|
||||||
|
|
||||||
const onHide = () => { |
|
||||||
setModalShow(false); |
|
||||||
setFeedback(null); |
|
||||||
}; |
|
||||||
|
|
||||||
const submitFormRef = useRef(); |
|
||||||
const bindSubmitForm = submitForm => { |
|
||||||
submitFormRef.current = submitForm; |
|
||||||
}; |
|
||||||
|
|
||||||
return ( |
|
||||||
<NewItemModal |
|
||||||
show={modalShow} |
|
||||||
title={t("button")} |
|
||||||
onSave={() => submitFormRef.current()} |
|
||||||
onClick={() => setFeedback(null)} |
|
||||||
{...{ feedback, loading, onHide }} |
|
||||||
> |
|
||||||
<NewUserForm {...{ userList, onSubmit, bindSubmitForm, feedback }} /> |
|
||||||
</NewItemModal> |
|
||||||
); |
|
||||||
}; |
|
||||||
|
|
||||||
const makePayload = data => ({ |
|
||||||
admin: data.isSynapseAdministrator, |
|
||||||
email: data.emailAddress, |
|
||||||
}); |
|
||||||
|
|
||||||
const makeUser = data => ({ |
|
||||||
userId: _genRandomString(), |
|
||||||
displayName: "", |
|
||||||
emailAddress: data.emailAddress, |
|
||||||
lastSeen: null, |
|
||||||
role: data.isSynapseAdministrator ? "administrator" : "collaborator", |
|
||||||
status: "active", |
|
||||||
}); |
|
||||||
|
|
||||||
const _genRandomString = () => Math.floor(Math.random() * 1000000).toString(); |
|
@ -0,0 +1,91 @@ |
|||||||
|
import React, { useRef, useState } from "react"; |
||||||
|
import PropTypes from "prop-types"; |
||||||
|
|
||||||
|
import { useMutate } from "restful-react"; |
||||||
|
import { useTranslation } from "react-i18next"; |
||||||
|
|
||||||
|
import NewItemModal from "./NewItemModal"; |
||||||
|
import NewUserForm from "./NewUserForm"; |
||||||
|
|
||||||
|
const NewUserModal = ({ modalShow, setModalShow, userList, newUserLocalEcho }) => { |
||||||
|
const { t } = useTranslation("usersTab"); |
||||||
|
|
||||||
|
const [feedback, setFeedback] = useState(null); |
||||||
|
|
||||||
|
const { mutate: post, loading } = useMutate({ |
||||||
|
verb: "POST", |
||||||
|
path: "watcha_register", |
||||||
|
}); |
||||||
|
|
||||||
|
const makePayload = data => ({ |
||||||
|
admin: data.isSynapseAdministrator, |
||||||
|
email: data.emailAddress, |
||||||
|
}); |
||||||
|
|
||||||
|
const genRandomString = () => Math.floor(Math.random() * 1000000).toString(); |
||||||
|
|
||||||
|
const makeUser = data => ({ |
||||||
|
userId: genRandomString(), |
||||||
|
displayName: "", |
||||||
|
emailAddress: data.emailAddress, |
||||||
|
lastSeen: null, |
||||||
|
role: data.isSynapseAdministrator ? "administrator" : "collaborator", |
||||||
|
status: "active", |
||||||
|
}); |
||||||
|
|
||||||
|
const onSubmit = data => { |
||||||
|
const payload = makePayload(data); |
||||||
|
post(payload) |
||||||
|
.then(() => { |
||||||
|
const user = makeUser(data); |
||||||
|
newUserLocalEcho(user); |
||||||
|
setFeedback({ variant: "success", message: t("success") }); |
||||||
|
}) |
||||||
|
.catch(() => setFeedback({ variant: "danger", message: t("danger") })); |
||||||
|
}; |
||||||
|
|
||||||
|
const onHide = () => { |
||||||
|
setModalShow(false); |
||||||
|
setFeedback(null); |
||||||
|
}; |
||||||
|
|
||||||
|
const submitFormRef = useRef(); |
||||||
|
const bindSubmitForm = submitForm => { |
||||||
|
submitFormRef.current = submitForm; |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<NewItemModal |
||||||
|
show={modalShow} |
||||||
|
title={t("button")} |
||||||
|
onSave={() => submitFormRef.current()} |
||||||
|
onClick={() => setFeedback(null)} |
||||||
|
{...{ feedback, loading, onHide }} |
||||||
|
> |
||||||
|
<NewUserForm {...{ userList, onSubmit, bindSubmitForm, feedback }} /> |
||||||
|
</NewItemModal> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
NewUserModal.defaultProps = { |
||||||
|
userList: null, |
||||||
|
}; |
||||||
|
|
||||||
|
NewUserModal.propTypes = { |
||||||
|
modalShow: PropTypes.bool.isRequired, |
||||||
|
setModalShow: PropTypes.func.isRequired, |
||||||
|
userList: PropTypes.arrayOf( |
||||||
|
PropTypes.shape({ |
||||||
|
userId: PropTypes.string.isRequired, |
||||||
|
itemId: PropTypes.string, |
||||||
|
displayName: PropTypes.string.isRequired, |
||||||
|
emailAddress: PropTypes.string.isRequired, |
||||||
|
lastSeen: PropTypes.number, |
||||||
|
role: PropTypes.string.isRequired, |
||||||
|
creationTs: PropTypes.number, |
||||||
|
}) |
||||||
|
), |
||||||
|
newUserLocalEcho: PropTypes.func.isRequired, |
||||||
|
}; |
||||||
|
|
||||||
|
export default NewUserModal; |
@ -1,10 +0,0 @@ |
|||||||
import React from "react"; |
|
||||||
|
|
||||||
import "./css/PanelRow.scss"; |
|
||||||
|
|
||||||
export default ({ label, value }) => ( |
|
||||||
<div className="PanelRow"> |
|
||||||
<div className="PanelRow_label">{label}</div> |
|
||||||
<div className="PanelRow_value">{value}</div> |
|
||||||
</div> |
|
||||||
); |
|
@ -0,0 +1,22 @@ |
|||||||
|
import React from "react"; |
||||||
|
import PropTypes from "prop-types"; |
||||||
|
|
||||||
|
import "./css/PanelRow.scss"; |
||||||
|
|
||||||
|
const PanelRow = ({ label, value }) => ( |
||||||
|
<div className="PanelRow"> |
||||||
|
<div className="PanelRow_label">{label}</div> |
||||||
|
<div className="PanelRow_value">{value}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
|
||||||
|
PanelRow.defaultProps = { |
||||||
|
value: "", |
||||||
|
}; |
||||||
|
|
||||||
|
PanelRow.propTypes = { |
||||||
|
label: PropTypes.node.isRequired, |
||||||
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), |
||||||
|
}; |
||||||
|
|
||||||
|
export default PanelRow; |
@ -1,5 +0,0 @@ |
|||||||
import React from "react"; |
|
||||||
|
|
||||||
import "./css/Status.scss"; |
|
||||||
|
|
||||||
export default ({ status, t }) => <span className={`Status ${status}`} title={t(`status.${status}`)} />; |
|
@ -0,0 +1,13 @@ |
|||||||
|
import React from "react"; |
||||||
|
import PropTypes from "prop-types"; |
||||||
|
|
||||||
|
import "./css/Status.scss"; |
||||||
|
|
||||||
|
const Status = ({ status, t }) => <span className={`Status ${status}`} title={t(`status.${status}`)} />; |
||||||
|
|
||||||
|
Status.propTypes = { |
||||||
|
status: PropTypes.string.isRequired, |
||||||
|
t: PropTypes.func.isRequired, |
||||||
|
}; |
||||||
|
|
||||||
|
export default Status; |
Loading…
Reference in new issue